suricata
app-layer-htp-body.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2011 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  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
23  * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
24  * \author Brian Rectanus <brectanu@gmail.com>
25  *
26  * This file provides a HTTP protocol support for the engine using HTP library.
27  */
28 
29 #include "suricata.h"
30 #include "suricata-common.h"
31 #include "debug.h"
32 #include "decode.h"
33 #include "threads.h"
34 
35 #include "util-print.h"
36 #include "util-pool.h"
37 #include "util-radix-tree.h"
38 
39 #include "stream-tcp-private.h"
40 #include "stream-tcp-reassemble.h"
41 #include "stream-tcp.h"
42 #include "stream.h"
43 
44 #include "app-layer-protos.h"
45 #include "app-layer-parser.h"
46 #include "app-layer-htp.h"
47 #include "app-layer-htp-body.h"
48 
49 #include "util-spm.h"
50 #include "util-debug.h"
51 #include "app-layer-htp-file.h"
52 #include "util-time.h"
53 
54 #include "util-unittest.h"
55 #include "util-unittest-helper.h"
56 #include "flow-util.h"
57 
58 #include "detect-engine.h"
59 #include "detect-engine-state.h"
60 #include "detect-parse.h"
61 
62 #include "conf.h"
63 
64 #include "util-memcmp.h"
65 
66 static StreamingBufferConfig default_cfg = { 0, 3072, HTPMalloc, HTPCalloc, HTPRealloc, HTPFree };
67 
68 /**
69  * \brief Append a chunk of body to the HtpBody struct
70  *
71  * \param body pointer to the HtpBody holding the list
72  * \param data pointer to the data of the chunk
73  * \param len length of the chunk pointed by data
74  *
75  * \retval 0 ok
76  * \retval -1 error
77  */
78 int HtpBodyAppendChunk(const HTPCfgDir *hcfg, HtpBody *body,
79  const uint8_t *data, uint32_t len)
80 {
81  SCEnter();
82 
83  HtpBodyChunk *bd = NULL;
84 
85  if (len == 0 || data == NULL) {
86  SCReturnInt(0);
87  }
88 
89  if (body->sb == NULL) {
90  const StreamingBufferConfig *cfg = hcfg ? &hcfg->sbcfg : &default_cfg;
91  body->sb = StreamingBufferInit(cfg);
92  if (body->sb == NULL)
93  SCReturnInt(-1);
94  }
95 
96  /* New chunk */
97  bd = (HtpBodyChunk *)HTPCalloc(1, sizeof(HtpBodyChunk));
98  if (bd == NULL) {
99  SCReturnInt(-1);
100  }
101 
102  if (StreamingBufferAppend(body->sb, &bd->sbseg, data, len) != 0) {
103  HTPFree(bd, sizeof(HtpBodyChunk));
104  SCReturnInt(-1);
105  }
106 
107  if (body->first == NULL) {
108  body->first = body->last = bd;
109  } else {
110  body->last->next = bd;
111  body->last = bd;
112  }
113  body->content_len_so_far += len;
114 
115  SCLogDebug("body %p", body);
116 
117  SCReturnInt(0);
118 }
119 
120 /**
121  * \brief Print the information and chunks of a Body
122  * \param body pointer to the HtpBody holding the list
123  * \retval none
124  */
126 {
127  if (SCLogDebugEnabled()||1) {
128  SCEnter();
129 
130  if (body->first == NULL)
131  return;
132 
133  HtpBodyChunk *cur = NULL;
134  SCLogDebug("--- Start body chunks at %p ---", body);
135  printf("--- Start body chunks at %p ---\n", body);
136  for (cur = body->first; cur != NULL; cur = cur->next) {
137  const uint8_t *data = NULL;
138  uint32_t data_len = 0;
139  StreamingBufferSegmentGetData(body->sb, &cur->sbseg, &data, &data_len);
140  SCLogDebug("Body %p; data %p, len %"PRIu32, body, data, data_len);
141  printf("Body %p; data %p, len %"PRIu32"\n", body, data, data_len);
142  PrintRawDataFp(stdout, data, data_len);
143  }
144  SCLogDebug("--- End body chunks at %p ---", body);
145  }
146 }
147 
148 /**
149  * \brief Free the information held in the request body
150  * \param body pointer to the HtpBody holding the list
151  * \retval none
152  */
153 void HtpBodyFree(HtpBody *body)
154 {
155  SCEnter();
156 
157  SCLogDebug("removing chunks of body %p", body);
158 
159  HtpBodyChunk *cur = NULL;
160  HtpBodyChunk *prev = NULL;
161 
162  prev = body->first;
163  while (prev != NULL) {
164  cur = prev->next;
165  HTPFree(prev, sizeof(HtpBodyChunk));
166  prev = cur;
167  }
168  body->first = body->last = NULL;
169 
170  StreamingBufferFree(body->sb);
171 }
172 
173 /**
174  * \brief Free request body chunks that are already fully parsed.
175  *
176  * \param state htp_state, with reference to our config
177  * \param body the body to prune
178  * \param direction STREAM_TOSERVER (request), STREAM_TOCLIENT (response)
179  *
180  * \retval none
181  */
182 void HtpBodyPrune(HtpState *state, HtpBody *body, int direction)
183 {
184  SCEnter();
185 
186  if (body == NULL || body->first == NULL) {
187  SCReturn;
188  }
189 
190  if (body->body_parsed == 0) {
191  SCReturn;
192  }
193 
194  /* get the configured inspect sizes. Default to response values */
195  uint32_t min_size = state->cfg->response.inspect_min_size;
196  uint32_t window = state->cfg->response.inspect_window;
197 
198  if (direction == STREAM_TOSERVER) {
199  min_size = state->cfg->request.inspect_min_size;
200  window = state->cfg->request.inspect_window;
201  }
202 
203  uint64_t max_window = ((min_size > window) ? min_size : window);
204  uint64_t in_flight = body->content_len_so_far - body->body_inspected;
205 
206  /* Special case. If body_inspected is not being updated, we make sure that
207  * we prune the body. We allow for some extra size/room as we may be called
208  * multiple times on uninspected body chunk additions if a large block of
209  * data was ack'd at once. Want to avoid pruning before inspection. */
210  if (in_flight > (max_window * 3)) {
211  body->body_inspected = body->content_len_so_far - max_window;
212  } else if (body->body_inspected < max_window) {
213  SCReturn;
214  }
215 
216  uint64_t left_edge = body->body_inspected;
217  if (left_edge <= min_size || left_edge <= window)
218  left_edge = 0;
219  if (left_edge)
220  left_edge -= window;
221 
222  if (left_edge) {
223  SCLogDebug("sliding body to offset %"PRIu64, left_edge);
224  StreamingBufferSlideToOffset(body->sb, left_edge);
225  }
226 
227  SCLogDebug("pruning chunks of body %p", body);
228 
229  HtpBodyChunk *cur = body->first;
230  while (cur != NULL) {
231  HtpBodyChunk *next = cur->next;
232  SCLogDebug("cur %p", cur);
233 
234  if (!StreamingBufferSegmentIsBeforeWindow(body->sb, &cur->sbseg)) {
235  SCLogDebug("not removed");
236  break;
237  }
238 
239  body->first = next;
240  if (body->last == cur) {
241  body->last = next;
242  }
243 
244  HTPFree(cur, sizeof(HtpBodyChunk));
245 
246  cur = next;
247  SCLogDebug("removed");
248  }
249 
250  SCReturn;
251 }
HtpState_::cfg
const struct HTPCfgRec_ * cfg
Definition: app-layer-htp.h:257
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
StreamingBufferFree
void StreamingBufferFree(StreamingBuffer *sb)
Definition: util-streaming-buffer.c:145
flow-util.h
stream-tcp.h
HTPCfgDir_
Definition: app-layer-htp.h:154
HtpBody_::sb
StreamingBuffer * sb
Definition: app-layer-htp.h:195
HTPCfgRec_::response
HTPCfgDir response
Definition: app-layer-htp.h:179
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
threads.h
HtpBody_::last
HtpBodyChunk * last
Definition: app-layer-htp.h:193
stream-tcp-reassemble.h
HTPRealloc
void * HTPRealloc(void *ptr, size_t orig_size, size_t size)
Definition: app-layer-htp-mem.c:171
HTPCfgDir_::inspect_window
uint32_t inspect_window
Definition: app-layer-htp.h:157
util-unittest.h
HtpBody_::first
HtpBodyChunk * first
Definition: app-layer-htp.h:192
HtpState_
Definition: app-layer-htp.h:247
util-unittest-helper.h
app-layer-htp-file.h
util-memcmp.h
HtpBody_::content_len_so_far
uint64_t content_len_so_far
Definition: app-layer-htp.h:198
app-layer-htp.h
decode.h
util-debug.h
HtpBody_::body_parsed
uint64_t body_parsed
Definition: app-layer-htp.h:200
StreamingBufferInit
StreamingBuffer * StreamingBufferInit(const StreamingBufferConfig *cfg)
Definition: util-streaming-buffer.c:112
StreamingBufferSegmentIsBeforeWindow
int StreamingBufferSegmentIsBeforeWindow(const StreamingBuffer *sb, const StreamingBufferSegment *seg)
Definition: util-streaming-buffer.c:714
HTPCfgDir_::inspect_min_size
uint32_t inspect_min_size
Definition: app-layer-htp.h:156
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
HtpBodyAppendChunk
int HtpBodyAppendChunk(const HTPCfgDir *hcfg, HtpBody *body, const uint8_t *data, uint32_t len)
Append a chunk of body to the HtpBody struct.
Definition: app-layer-htp-body.c:78
HTPCalloc
void * HTPCalloc(size_t n, size_t size)
Definition: app-layer-htp-mem.c:154
util-time.h
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:141
app-layer-parser.h
SCReturn
#define SCReturn
Definition: util-debug.h:302
stream.h
app-layer-htp-body.h
HTPCfgDir_::sbcfg
StreamingBufferConfig sbcfg
Definition: app-layer-htp.h:158
stream-tcp-private.h
conf.h
util-radix-tree.h
HtpBodyPrune
void HtpBodyPrune(HtpState *state, HtpBody *body, int direction)
Free request body chunks that are already fully parsed.
Definition: app-layer-htp-body.c:182
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
HtpBody_
Definition: app-layer-htp.h:191
suricata-common.h
HTPCfgRec_::request
HTPCfgDir request
Definition: app-layer-htp.h:178
HtpBodyChunk_
Definition: app-layer-htp.h:183
util-spm.h
StreamingBufferConfig_
Definition: util-streaming-buffer.h:64
HtpBodyChunk_::next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:184
StreamingBufferSlideToOffset
void StreamingBufferSlideToOffset(StreamingBuffer *sb, uint64_t offset)
slide to absolute offset
Definition: util-streaming-buffer.c:506
detect-parse.h
app-layer-protos.h
suricata.h
HTPMalloc
void * HTPMalloc(size_t size)
Definition: app-layer-htp-mem.c:137
HtpBodyPrint
void HtpBodyPrint(HtpBody *body)
Print the information and chunks of a Body.
Definition: app-layer-htp-body.c:125
StreamingBufferAppend
int StreamingBufferAppend(StreamingBuffer *sb, StreamingBufferSegment *seg, const uint8_t *data, uint32_t data_len)
Definition: util-streaming-buffer.c:571
HTPFree
void HTPFree(void *ptr, size_t size)
Definition: app-layer-htp-mem.c:191
StreamingBufferSegmentGetData
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
Definition: util-streaming-buffer.c:785
util-pool.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
HtpBodyFree
void HtpBodyFree(HtpBody *body)
Free the information held in the request body.
Definition: app-layer-htp-body.c:153
HtpBodyChunk_::sbseg
StreamingBufferSegment sbseg
Definition: app-layer-htp.h:186
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:647
debug.h
HtpBody_::body_inspected
uint64_t body_inspected
Definition: app-layer-htp.h:202