suricata
detect-http-header-common.c
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  * \ingroup httplayer
20  *
21  * @{
22  */
23 
24 #include "suricata-common.h"
25 #include "threads.h"
26 #include "decode.h"
27 
28 #include "detect.h"
29 #include "detect-parse.h"
30 #include "detect-engine.h"
31 #include "detect-engine-mpm.h"
32 #include "detect-engine-state.h"
35 #include "detect-content.h"
36 #include "detect-pcre.h"
37 
38 #include "flow.h"
39 #include "flow-var.h"
40 #include "flow-util.h"
41 
42 #include "util-debug.h"
43 #include "util-unittest.h"
44 #include "util-unittest-helper.h"
45 #include "util-spm.h"
46 #include "util-print.h"
47 
48 #include "app-layer.h"
49 #include "app-layer-parser.h"
50 
51 #include "app-layer-htp.h"
52 #include "detect-http-header.h"
53 #include "stream-tcp.h"
54 
55 #include "util-print.h"
56 
58 
59 static inline int CreateSpace(HttpHeaderThreadData *td, uint64_t size);
60 
61 void *HttpHeaderThreadDataInit(void *data)
62 {
63  HttpHeaderThreadData *td = SCCalloc(1, sizeof(*td));
64  if (td != NULL) {
65  if (data == NULL) {
66  td->tx_step = 4;
67  td->size_step = 512;
68  } else {
70  td->tx_step = c->tx_step;
71  td->size_step = c->size_step;
72  }
73 
74  /* initialize minimal buffers */
75  (void)CreateSpace(td, 1);
76  int i;
77  for (i = 0; i < td->buffers_size; i++) {
78  (void)HttpHeaderExpandBuffer(td, &td->buffers[i], 1);
79  }
80  }
81  return td;
82 }
83 
84 void HttpHeaderThreadDataFree(void *data)
85 {
86  HttpHeaderThreadData *hdrnames = data;
87 
88  int i;
89  for (i = 0; i < hdrnames->buffers_size; i++) {
90  if (hdrnames->buffers[i].buffer)
91  SCFree(hdrnames->buffers[i].buffer);
92  if (hdrnames->buffers[i].size) {
93  SCLogDebug("hdrnames->buffers[%d].size %u (%u)",
94  i, hdrnames->buffers[i].size, hdrnames->buffers_size);
95  }
96  }
97  SCFree(hdrnames->buffers);
98  SCFree(hdrnames);
99 }
100 
101 static void Reset(HttpHeaderThreadData *hdrnames, uint64_t tick)
102 {
103  uint16_t i;
104  for (i = 0; i < hdrnames->buffers_list_len; i++) {
105  hdrnames->buffers[i].len = 0;
106  }
107  hdrnames->buffers_list_len = 0;
108  hdrnames->start_tx_id = 0;
109  hdrnames->tick = tick;
110 }
111 
112 static inline int CreateSpace(HttpHeaderThreadData *td, uint64_t size)
113 {
114  if (size >= SHRT_MAX)
115  return -1;
116 
117  if (size > td->buffers_size) {
118  uint16_t extra = td->tx_step;
119  while (td->buffers_size + extra < size) {
120  extra += td->tx_step;
121  }
122  SCLogDebug("adding %u to the buffer", extra);
123 
124  void *ptmp = SCRealloc(td->buffers,
125  (td->buffers_size + extra) * sizeof(HttpHeaderBuffer));
126  if (ptmp == NULL) {
127  SCFree(td->buffers);
128  td->buffers = NULL;
129  td->buffers_size = 0;
130  td->buffers_list_len = 0;
131  return -1;
132  }
133  td->buffers = ptmp;
134  memset(td->buffers + td->buffers_size, 0, extra * sizeof(HttpHeaderBuffer));
135  td->buffers_size += extra;
136  }
137  return 0;
138 }
139 
141  HttpHeaderBuffer *buf, uint32_t size)
142 {
143  size_t extra = td->size_step;
144  while ((buf->size + extra) < (size + buf->len)) {
145  extra += td->size_step;
146  }
147  SCLogDebug("adding %"PRIuMAX" to the buffer", (uintmax_t)extra);
148 
149  uint8_t *new_buffer = SCRealloc(buf->buffer, buf->size + extra);
150  if (unlikely(new_buffer == NULL)) {
151  buf->len = 0;
152  return -1;
153  }
154  buf->buffer = new_buffer;
155  buf->size += extra;
156  return 0;
157 }
158 
160  Flow *f, uint8_t flags, uint64_t tx_id, const int keyword_id,
161  HttpHeaderThreadData **ret_hdr_td)
162 {
163  int index = 0;
164  *ret_hdr_td = NULL;
165 
166  HttpHeaderThreadData *hdr_td =
167  DetectThreadCtxGetGlobalKeywordThreadCtx(det_ctx, keyword_id);
168  if (hdr_td == NULL)
169  return NULL;
170  if (hdr_td->tick != det_ctx->ticker)
171  Reset(hdr_td, det_ctx->ticker);
172  *ret_hdr_td = hdr_td;
173 
174  if (hdr_td->buffers_list_len == 0) {
175  /* get the inspect id to use as a 'base id' */
176  uint64_t base_inspect_id = AppLayerParserGetTransactionInspectId(f->alparser, flags);
177  BUG_ON(base_inspect_id > tx_id);
178  /* see how many space we need for the current tx_id */
179  uint64_t txs = (tx_id - base_inspect_id) + 1;
180  if (CreateSpace(hdr_td, txs) < 0)
181  return NULL;
182 
183  index = (tx_id - base_inspect_id);
184  hdr_td->start_tx_id = base_inspect_id;
185  hdr_td->buffers_list_len = txs;
186  } else {
187  /* tx fits in our current buffers */
188  if ((tx_id - hdr_td->start_tx_id) < hdr_td->buffers_list_len) {
189  /* if we previously reassembled, return that buffer */
190  if (hdr_td->buffers[(tx_id - hdr_td->start_tx_id)].len != 0) {
191  return &hdr_td->buffers[(tx_id - hdr_td->start_tx_id)];
192  }
193  /* otherwise fall through */
194  } else {
195  /* not enough space, lets expand */
196  uint64_t txs = (tx_id - hdr_td->start_tx_id) + 1;
197  if (CreateSpace(hdr_td, txs) < 0)
198  return NULL;
199 
200  hdr_td->buffers_list_len = txs;
201  }
202  index = (tx_id - hdr_td->start_tx_id);
203  }
204  HttpHeaderBuffer *buf = &hdr_td->buffers[index];
205  return buf;
206 }
uint16_t flags
#define SCLogDebug(...)
Definition: util-debug.h:335
#define BUG_ON(x)
void HttpHeaderThreadDataFree(void *data)
int HttpHeaderExpandBuffer(HttpHeaderThreadData *td, HttpHeaderBuffer *buf, uint32_t size)
#define unlikely(expr)
Definition: util-optimize.h:35
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
#define SCCalloc(nm, a)
Definition: util-mem.h:197
Data structures and function prototypes for keeping state for the detection engine.
HttpHeaderBuffer * HttpHeaderGetBufferSpaceForTXID(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, uint64_t tx_id, const int keyword_id, HttpHeaderThreadData **ret_hdr_td)
void * HttpHeaderThreadDataInit(void *data)
#define index
Definition: win32-misc.h:29
#define SCRealloc(x, a)
Definition: util-mem.h:182
#define SCFree(a)
Definition: util-mem.h:228
uint16_t tx_id
void * DetectThreadCtxGetGlobalKeywordThreadCtx(DetectEngineThreadCtx *det_ctx, int id)
Retrieve thread local keyword ctx by id.
Flow data structure.
Definition: flow.h:324
AppLayerParserState * alparser
Definition: flow.h:432