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