suricata
detect-http-headers-stub.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2017 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  * Stub for per HTTP header detection keyword. Meant to be included into
20  * a C file.
21  */
22 
23 /**
24  * \ingroup httplayer
25  *
26  * @{
27  */
28 
29 #include "suricata-common.h"
30 #include "threads.h"
31 #include "decode.h"
32 #include "flow.h"
33 #include "app-layer.h"
34 #include "app-layer-parser.h"
35 #include "app-layer-htp.h"
36 
37 #include "detect.h"
38 #include "detect-parse.h"
39 #include "detect-engine.h"
40 #include "detect-engine-mpm.h"
41 #include "detect-engine-state.h"
44 #include "detect-content.h"
45 #include "detect-http-header.h"
46 
47 #include "util-debug.h"
48 
49 static int g_buffer_id = 0;
50 
51 #ifdef KEYWORD_TOSERVER
52 /** \brief HTTP Headers Mpm prefilter callback
53  *
54  * \param det_ctx detection engine thread ctx
55  * \param p packet to inspect
56  * \param f flow to inspect
57  * \param txv tx to inspect
58  * \param pectx inspection context
59  */
60 static void PrefilterTxHttpRequestHeader(DetectEngineThreadCtx *det_ctx,
61  const void *pectx,
62  Packet *p, Flow *f, void *txv,
63  const uint64_t idx, const uint8_t flags)
64 {
65  SCEnter();
66  const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
67  htp_tx_t *tx = (htp_tx_t *)txv;
68 
69  if (tx->request_headers == NULL)
70  return;
71 
72  htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->request_headers,
73  HEADER_NAME);
74  if (h == NULL || h->value == NULL) {
75  SCLogDebug("HTTP %s header not present in this request", HEADER_NAME);
76  return;
77  }
78 
79  const uint32_t buffer_len = bstr_len(h->value);
80  const uint8_t *buffer = bstr_ptr(h->value);
81 
82  if (buffer_len >= mpm_ctx->minlen) {
83  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
84  &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
85  }
86 }
87 #if 0
88 static void PrefilterTxHttpRequestTrailers(DetectEngineThreadCtx *det_ctx,
89  const void *pectx,
90  Packet *p, Flow *f, void *txv,
91  const uint64_t idx, const uint8_t flags)
92 {
93  SCEnter();
94 
95  const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
96  htp_tx_t *tx = (htp_tx_t *)txv;
97 
98  if (tx->request_headers == NULL)
99  return;
100  const HtpTxUserData *htud = (const HtpTxUserData *)htp_tx_get_user_data(tx);
101  /* if the request wasn't flagged as having a trailer, we skip */
102  if (htud && !htud->request_has_trailers)
103  return;
104 
105  HtpState *htp_state = f->alstate;
106  uint32_t buffer_len = 0;
107  const uint8_t *buffer = DetectEngineHHDGetBufferForTX(tx, idx,
108  NULL, det_ctx,
109  f, htp_state,
110  flags,
111  &buffer_len);
112 
113  if (buffer_len >= mpm_ctx->minlen) {
114  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
115  &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
116  }
117 }
118 #endif
119 static int PrefilterTxHttpRequestHeaderRegister(DetectEngineCtx *de_ctx,
120  SigGroupHead *sgh, MpmCtx *mpm_ctx)
121 {
122  SCEnter();
123 
124  int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttpRequestHeader,
125  ALPROTO_HTTP, HTP_REQUEST_HEADERS,
126  mpm_ctx, NULL, KEYWORD_NAME " (request)");
127  return r;
128 #if 0
129  if (r != 0)
130  return r;
131  return PrefilterAppendTxEngine(sgh, PrefilterTxHttpRequestTrailers,
132  ALPROTO_HTTP, HTP_REQUEST_TRAILER,
133  mpm_ctx, NULL, "http_header (request)");
134 #endif
135 }
136 #endif
137 
138 #ifdef KEYWORD_TOCLIENT
139 /** \brief HTTP Headers Mpm prefilter callback
140  *
141  * \param det_ctx detection engine thread ctx
142  * \param p packet to inspect
143  * \param f flow to inspect
144  * \param txv tx to inspect
145  * \param pectx inspection context
146  */
147 static void PrefilterTxHttpResponseHeader(DetectEngineThreadCtx *det_ctx,
148  const void *pectx,
149  Packet *p, Flow *f, void *txv,
150  const uint64_t idx, const uint8_t flags)
151 {
152  SCEnter();
153  const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
154  htp_tx_t *tx = (htp_tx_t *)txv;
155 
156  if (tx->response_headers == NULL)
157  return;
158 
159  htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers,
160  HEADER_NAME);
161  if (h == NULL || h->value == NULL) {
162  SCLogDebug("HTTP %s header not present in this request", HEADER_NAME);
163  return;
164  }
165 
166  const uint32_t buffer_len = bstr_len(h->value);
167  const uint8_t *buffer = bstr_ptr(h->value);
168 
169  if (buffer_len >= mpm_ctx->minlen) {
170  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
171  &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
172  }
173 }
174 #if 0
175 static void PrefilterTxHttpResponseTrailers(DetectEngineThreadCtx *det_ctx,
176  const void *pectx,
177  Packet *p, Flow *f, void *txv,
178  const uint64_t idx, const uint8_t flags)
179 {
180  SCEnter();
181 
182  const MpmCtx *mpm_ctx = (MpmCtx *)pectx;
183  htp_tx_t *tx = (htp_tx_t *)txv;
184 
185  if (tx->response_headers == NULL)
186  return;
187  const HtpTxUserData *htud = (const HtpTxUserData *)htp_tx_get_user_data(tx);
188  /* if the request wasn't flagged as having a trailer, we skip */
189  if (htud && !htud->response_has_trailers)
190  return;
191 
192  HtpState *htp_state = f->alstate;
193  uint32_t buffer_len = 0;
194  const uint8_t *buffer = DetectEngineHHDGetBufferForTX(tx, idx,
195  NULL, det_ctx,
196  f, htp_state,
197  flags,
198  &buffer_len);
199 
200  if (buffer_len >= mpm_ctx->minlen) {
201  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
202  &det_ctx->mtcu, &det_ctx->pmq, buffer, buffer_len);
203  }
204 }
205 #endif
206 static int PrefilterTxHttpResponseHeaderRegister(DetectEngineCtx *de_ctx,
207  SigGroupHead *sgh, MpmCtx *mpm_ctx)
208 {
209  SCEnter();
210 
211  int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterTxHttpResponseHeader,
212  ALPROTO_HTTP, HTP_RESPONSE_HEADERS,
213  mpm_ctx, NULL, KEYWORD_NAME " (response)");
214  return r;
215 #if 0
216  if (r != 0)
217  return r;
218  return PrefilterAppendTxEngine(sgh, PrefilterTxHttpRequestTrailers,
219  ALPROTO_HTTP, HTP_REQUEST_TRAILER,
220  mpm_ctx, NULL, "http_header (request)");
221 #endif
222 }
223 #endif
224 
225 #ifdef KEYWORD_TOSERVER
226 static int InspectEngineHttpRequestHeader(ThreadVars *tv,
227  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
228  const Signature *s, const SigMatchData *smd,
229  Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
230 {
231  htp_tx_t *tx = (htp_tx_t *)txv;
232  if (tx->request_headers == NULL)
233  goto end;
234 
235  htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->request_headers,
236  HEADER_NAME);
237  if (h == NULL || h->value == NULL) {
238  SCLogDebug("HTTP UA header not present in this request");
239  goto end;
240  }
241 
242  const uint32_t buffer_len = bstr_len(h->value);
243  uint8_t *buffer = bstr_ptr(h->value);
244 
245  if (buffer_len == 0)
246  goto end;
247 
248  det_ctx->buffer_offset = 0;
249  det_ctx->discontinue_matching = 0;
250  det_ctx->inspection_recursion_counter = 0;
251  int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd,
252  f,
253  buffer, buffer_len,
256  if (r == 1)
258 
259  end:
260  if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_REQUEST_HEADERS)
262  else
264 }
265 #endif
266 #ifdef KEYWORD_TOCLIENT
267 static int InspectEngineHttpResponseHeader(ThreadVars *tv,
268  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
269  const Signature *s, const SigMatchData *smd,
270  Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
271 {
272  htp_tx_t *tx = (htp_tx_t *)txv;
273  if (tx->response_headers == NULL)
274  goto end;
275 
276  htp_header_t *h = (htp_header_t *)htp_table_get_c(tx->response_headers,
277  HEADER_NAME);
278  if (h == NULL || h->value == NULL) {
279  SCLogDebug("HTTP header not present in this request");
280  goto end;
281  }
282 
283  const uint32_t buffer_len = bstr_len(h->value);
284  uint8_t *buffer = bstr_ptr(h->value);
285 
286  if (buffer_len == 0)
287  goto end;
288 
289  det_ctx->buffer_offset = 0;
290  det_ctx->discontinue_matching = 0;
291  det_ctx->inspection_recursion_counter = 0;
292  int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd,
293  f,
294  buffer, buffer_len,
297  if (r == 1)
299 
300  end:
301  if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP, tx, flags) > HTP_RESPONSE_HEADERS)
303  else
305 }
306 #endif
307 
308 /**
309  * \brief The setup function for the http_header keyword for a signature.
310  *
311  * \param de_ctx Pointer to the detection engine context.
312  * \param s Pointer to signature for the current Signature being parsed
313  * from the rules.
314  * \param m Pointer to the head of the SigMatchs for the current rule
315  * being parsed.
316  * \param arg Pointer to the string holding the keyword value.
317  *
318  * \retval 0 On success.
319  * \retval -1 On failure.
320  */
321 static int DetectHttpHeadersSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
322 {
323  s->init_data->list = g_buffer_id;
324  return 0;
325 }
326 
327 static void DetectHttpHeadersRegisterStub(void)
328 {
330  sigmatch_table[KEYWORD_ID].desc = KEYWORD_NAME " sticky buffer for the " BUFFER_DESC;
332  sigmatch_table[KEYWORD_ID].Setup = DetectHttpHeadersSetup;
334 #ifdef KEYWORD_TOSERVER
336  PrefilterTxHttpRequestHeaderRegister);
337 #endif
338 #ifdef KEYWORD_TOCLIENT
340  PrefilterTxHttpResponseHeaderRegister);
341 #endif
342 #ifdef KEYWORD_TOSERVER
344  ALPROTO_HTTP, SIG_FLAG_TOSERVER, HTP_REQUEST_HEADERS,
345  InspectEngineHttpRequestHeader);
346 #endif
347 #ifdef KEYWORD_TOCLIENT
349  ALPROTO_HTTP, SIG_FLAG_TOCLIENT, HTP_RESPONSE_HEADERS,
350  InspectEngineHttpResponseHeader);
351 #endif
352 
354 
355  g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
356 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1403
SignatureInitData * init_data
Definition: detect.h:560
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1146
#define SCLogDebug(...)
Definition: util-debug.h:335
uint16_t minlen
Definition: util-mpm.h:95
uint16_t discontinue_matching
Definition: detect.h:1026
void DetectAppLayerMpmRegister(const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx))
register an app layer keyword for mpm
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
Data needed for Match()
Definition: detect.h:333
Container for matching data for a signature group.
Definition: detect.h:1295
#define BUFFER_DESC
uint32_t buffer_offset
Definition: detect.h:991
const char * name
Definition: detect.h:1160
Signature container.
Definition: detect.h:492
#define KEYWORD_ID
uint8_t response_has_trailers
main detection engine ctx
Definition: detect.h:720
#define KEYWORD_DOC
void * alstate
Definition: flow.h:436
int DetectBufferTypeGetByName(const char *name)
#define SIG_FLAG_TOCLIENT
Definition: detect.h:244
#define DETECT_ENGINE_INSPECT_SIG_MATCH
uint16_t mpm_type
Definition: util-mpm.h:84
Data structures and function prototypes for keeping state for the detection engine.
#define HEADER_NAME
#define KEYWORD_NAME
#define SIG_FLAG_TOSERVER
Definition: detect.h:243
#define SCEnter(...)
Definition: util-debug.h:337
PrefilterRuleStore pmq
Definition: detect.h:1061
const char * desc
Definition: detect.h:1162
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
uint8_t request_has_trailers
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.h:165
uint16_t tx_id
MpmThreadCtx mtcu
Definition: detect.h:1059
#define SIGMATCH_NOOPT
Definition: detect.h:1328
int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Flow *f, uint8_t *buffer, uint32_t buffer_len, uint32_t stream_start_offset, uint8_t flags, uint8_t inspection_mode, void *data)
Run the actual payload match functions.
const char * url
Definition: detect.h:1163
int inspection_recursion_counter
Definition: detect.h:1038
#define DETECT_CI_FLAGS_SINGLE
#define DOC_URL
Definition: suricata.h:86
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:158
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, void(*PrefilterTxFunc)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f, void *tx, const uint64_t idx, const uint8_t flags), AppProto alproto, int tx_min_progress, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Per thread variable structure.
Definition: threadvars.h:57
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1154
Flow data structure.
Definition: flow.h:327
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback)
register inspect engine at start up time
#define BUFFER_NAME