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-common.h"
30 #include "app-layer-htp.h"
31 #include "app-layer-htp-mem.h"
32 #include "app-layer-htp-body.h"
33 #include "util-streaming-buffer.h"
34 #include "util-print.h"
35 
37 
38 /**
39  * \brief Append a chunk of body to the HtpBody struct
40  *
41  * \param body pointer to the HtpBody holding the list
42  * \param data pointer to the data of the chunk
43  * \param len length of the chunk pointed by data
44  *
45  * \retval 0 ok
46  * \retval -1 error
47  */
48 int HtpBodyAppendChunk(const HTPCfgDir *hcfg, HtpBody *body,
49  const uint8_t *data, uint32_t len)
50 {
51  SCEnter();
52 
53  HtpBodyChunk *bd = NULL;
54 
55  if (len == 0 || data == NULL) {
56  SCReturnInt(0);
57  }
58 
59  if (body->sb == NULL) {
61  if (body->sb == NULL)
62  SCReturnInt(-1);
63  }
64 
65  /* New chunk */
66  bd = (HtpBodyChunk *)HTPCalloc(1, sizeof(HtpBodyChunk));
67  if (bd == NULL) {
68  SCReturnInt(-1);
69  }
70 
71  if (StreamingBufferAppend(body->sb, &htp_sbcfg, &bd->sbseg, data, len) != 0) {
72  HTPFree(bd, sizeof(HtpBodyChunk));
73  SCReturnInt(-1);
74  }
75 
76  if (body->first == NULL) {
77  body->first = body->last = bd;
78  } else {
79  body->last->next = bd;
80  body->last = bd;
81  }
82  body->content_len_so_far += len;
83 
84  SCLogDebug("body %p", body);
85 
86  SCReturnInt(0);
87 }
88 
89 /**
90  * \brief Print the information and chunks of a Body
91  * \param body pointer to the HtpBody holding the list
92  * \retval none
93  */
94 
95 /**
96  * \brief Free the information held in the request body
97  * \param body pointer to the HtpBody holding the list
98  * \retval none
99  */
100 void HtpBodyFree(const HTPCfgDir *hcfg, HtpBody *body)
101 {
102  SCEnter();
103 
104  SCLogDebug("removing chunks of body %p", body);
105 
106  HtpBodyChunk *cur = NULL;
107  HtpBodyChunk *prev = NULL;
108 
109  prev = body->first;
110  while (prev != NULL) {
111  cur = prev->next;
112  HTPFree(prev, sizeof(HtpBodyChunk));
113  prev = cur;
114  }
115  body->first = body->last = NULL;
116 
118 }
119 
120 /**
121  * \brief Free request body chunks that are already fully parsed.
122  *
123  * \param state htp_state, with reference to our config
124  * \param body the body to prune
125  * \param direction STREAM_TOSERVER (request), STREAM_TOCLIENT (response)
126  *
127  * \retval none
128  */
129 void HtpBodyPrune(HtpState *state, HtpBody *body, int direction)
130 {
131  SCEnter();
132 
133  if (body == NULL || body->first == NULL) {
134  SCReturn;
135  }
136 
137  if (body->body_parsed == 0) {
138  SCReturn;
139  }
140 
141  const HTPCfgDir *cfg =
142  (direction == STREAM_TOCLIENT) ? &state->cfg->response : &state->cfg->request;
143  uint32_t min_size = cfg->inspect_min_size;
144  uint32_t window = cfg->inspect_window;
145  uint64_t max_window = ((min_size > window) ? min_size : window);
146  uint64_t in_flight = body->content_len_so_far - body->body_inspected;
147 
148  /* Special case. If body_inspected is not being updated, we make sure that
149  * we prune the body. We allow for some extra size/room as we may be called
150  * multiple times on uninspected body chunk additions if a large block of
151  * data was ack'd at once. Want to avoid pruning before inspection. */
152  if (in_flight > (max_window * 3)) {
153  body->body_inspected = body->content_len_so_far - max_window;
154  } else if (body->body_inspected < max_window) {
155  SCReturn;
156  }
157 
158  uint64_t left_edge = body->body_inspected;
159  if (left_edge <= min_size || left_edge <= window)
160  left_edge = 0;
161  if (left_edge)
162  left_edge -= window;
163 
164  if (left_edge) {
165  SCLogDebug("sliding body to offset %"PRIu64, left_edge);
166  StreamingBufferSlideToOffset(body->sb, &htp_sbcfg, left_edge);
167  }
168 
169  SCLogDebug("pruning chunks of body %p", body);
170 
171  HtpBodyChunk *cur = body->first;
172  while (cur != NULL) {
173  HtpBodyChunk *next = cur->next;
174  SCLogDebug("cur %p", cur);
175 
176  if (!StreamingBufferSegmentIsBeforeWindow(body->sb, &cur->sbseg)) {
177  SCLogDebug("not removed");
178  break;
179  }
180 
181  body->first = next;
182  if (body->last == cur) {
183  body->last = next;
184  }
185 
186  HTPFree(cur, sizeof(HtpBodyChunk));
187 
188  cur = next;
189  SCLogDebug("removed");
190  }
191 
192  SCReturn;
193 }
HtpState_::cfg
const struct HTPCfgRec_ * cfg
Definition: app-layer-htp.h:258
StreamingBufferSlideToOffset
void StreamingBufferSlideToOffset(StreamingBuffer *sb, const StreamingBufferConfig *cfg, uint64_t offset)
slide to absolute offset
Definition: util-streaming-buffer.c:1000
len
uint8_t len
Definition: app-layer-dnp3.h:2
HTPCfgDir_
Definition: app-layer-htp.h:150
HtpBody_::sb
StreamingBuffer * sb
Definition: app-layer-htp.h:190
HTPCfgRec_::response
HTPCfgDir response
Definition: app-layer-htp.h:172
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
StreamingBufferFree
void StreamingBufferFree(StreamingBuffer *sb, const StreamingBufferConfig *cfg)
Definition: util-streaming-buffer.c:295
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
HtpBody_::last
HtpBodyChunk * last
Definition: app-layer-htp.h:188
StreamingBufferAppend
int StreamingBufferAppend(StreamingBuffer *sb, const StreamingBufferConfig *cfg, StreamingBufferSegment *seg, const uint8_t *data, uint32_t data_len)
Definition: util-streaming-buffer.c:1069
HTPCfgDir_::inspect_window
uint32_t inspect_window
Definition: app-layer-htp.h:153
HtpBody_::first
HtpBodyChunk * first
Definition: app-layer-htp.h:187
HtpState_
Definition: app-layer-htp.h:244
HtpBody_::content_len_so_far
uint64_t content_len_so_far
Definition: app-layer-htp.h:193
app-layer-htp.h
HtpBody_::body_parsed
uint64_t body_parsed
Definition: app-layer-htp.h:195
StreamingBufferInit
StreamingBuffer * StreamingBufferInit(const StreamingBufferConfig *cfg)
Definition: util-streaming-buffer.c:249
StreamingBufferSegmentIsBeforeWindow
int StreamingBufferSegmentIsBeforeWindow(const StreamingBuffer *sb, const StreamingBufferSegment *seg)
Definition: util-streaming-buffer.c:1593
HTPCfgDir_::inspect_min_size
uint32_t inspect_min_size
Definition: app-layer-htp.h:152
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
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:48
HTPCalloc
void * HTPCalloc(size_t n, size_t size)
Definition: app-layer-htp-mem.c:152
SCReturn
#define SCReturn
Definition: util-debug.h:273
app-layer-htp-body.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:129
HtpBody_
Definition: app-layer-htp.h:186
suricata-common.h
HTPCfgRec_::request
HTPCfgDir request
Definition: app-layer-htp.h:171
util-streaming-buffer.h
HtpBodyChunk_
Definition: app-layer-htp.h:178
StreamingBufferConfig_
Definition: util-streaming-buffer.h:65
HtpBodyChunk_::next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:179
HtpBodyFree
void HtpBodyFree(const HTPCfgDir *hcfg, HtpBody *body)
Print the information and chunks of a Body.
Definition: app-layer-htp-body.c:100
app-layer-htp-mem.h
htp_sbcfg
StreamingBufferConfig htp_sbcfg
Definition: app-layer-htp.c:96
HTPFree
void HTPFree(void *ptr, size_t size)
Definition: app-layer-htp-mem.c:189
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
HtpBodyChunk_::sbseg
StreamingBufferSegment sbseg
Definition: app-layer-htp.h:181
HtpBody_::body_inspected
uint64_t body_inspected
Definition: app-layer-htp.h:197