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 void HtpBodyPrint(HtpBody *body)
95 {
96  if (SCLogDebugEnabled()||1) {
97  SCEnter();
98 
99  if (body->first == NULL)
100  return;
101 
102  HtpBodyChunk *cur = NULL;
103  SCLogDebug("--- Start body chunks at %p ---", body);
104  printf("--- Start body chunks at %p ---\n", body);
105  for (cur = body->first; cur != NULL; cur = cur->next) {
106  const uint8_t *data = NULL;
107  uint32_t data_len = 0;
108  StreamingBufferSegmentGetData(body->sb, &cur->sbseg, &data, &data_len);
109  SCLogDebug("Body %p; data %p, len %"PRIu32, body, data, data_len);
110  printf("Body %p; data %p, len %"PRIu32"\n", body, data, data_len);
111  PrintRawDataFp(stdout, data, data_len);
112  }
113  SCLogDebug("--- End body chunks at %p ---", body);
114  }
115 }
116 
117 /**
118  * \brief Free the information held in the request body
119  * \param body pointer to the HtpBody holding the list
120  * \retval none
121  */
122 void HtpBodyFree(const HTPCfgDir *hcfg, HtpBody *body)
123 {
124  SCEnter();
125 
126  SCLogDebug("removing chunks of body %p", body);
127 
128  HtpBodyChunk *cur = NULL;
129  HtpBodyChunk *prev = NULL;
130 
131  prev = body->first;
132  while (prev != NULL) {
133  cur = prev->next;
134  HTPFree(prev, sizeof(HtpBodyChunk));
135  prev = cur;
136  }
137  body->first = body->last = NULL;
138 
140 }
141 
142 /**
143  * \brief Free request body chunks that are already fully parsed.
144  *
145  * \param state htp_state, with reference to our config
146  * \param body the body to prune
147  * \param direction STREAM_TOSERVER (request), STREAM_TOCLIENT (response)
148  *
149  * \retval none
150  */
151 void HtpBodyPrune(HtpState *state, HtpBody *body, int direction)
152 {
153  SCEnter();
154 
155  if (body == NULL || body->first == NULL) {
156  SCReturn;
157  }
158 
159  if (body->body_parsed == 0) {
160  SCReturn;
161  }
162 
163  const HTPCfgDir *cfg =
164  (direction == STREAM_TOCLIENT) ? &state->cfg->response : &state->cfg->request;
165  uint32_t min_size = cfg->inspect_min_size;
166  uint32_t window = cfg->inspect_window;
167  uint64_t max_window = ((min_size > window) ? min_size : window);
168  uint64_t in_flight = body->content_len_so_far - body->body_inspected;
169 
170  /* Special case. If body_inspected is not being updated, we make sure that
171  * we prune the body. We allow for some extra size/room as we may be called
172  * multiple times on uninspected body chunk additions if a large block of
173  * data was ack'd at once. Want to avoid pruning before inspection. */
174  if (in_flight > (max_window * 3)) {
175  body->body_inspected = body->content_len_so_far - max_window;
176  } else if (body->body_inspected < max_window) {
177  SCReturn;
178  }
179 
180  uint64_t left_edge = body->body_inspected;
181  if (left_edge <= min_size || left_edge <= window)
182  left_edge = 0;
183  if (left_edge)
184  left_edge -= window;
185 
186  if (left_edge) {
187  SCLogDebug("sliding body to offset %"PRIu64, left_edge);
188  StreamingBufferSlideToOffset(body->sb, &htp_sbcfg, left_edge);
189  }
190 
191  SCLogDebug("pruning chunks of body %p", body);
192 
193  HtpBodyChunk *cur = body->first;
194  while (cur != NULL) {
195  HtpBodyChunk *next = cur->next;
196  SCLogDebug("cur %p", cur);
197 
198  if (!StreamingBufferSegmentIsBeforeWindow(body->sb, &cur->sbseg)) {
199  SCLogDebug("not removed");
200  break;
201  }
202 
203  body->first = next;
204  if (body->last == cur) {
205  body->last = next;
206  }
207 
208  HTPFree(cur, sizeof(HtpBodyChunk));
209 
210  cur = next;
211  SCLogDebug("removed");
212  }
213 
214  SCReturn;
215 }
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
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:135
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:151
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
HtpBodyPrint
void HtpBodyPrint(HtpBody *body)
Print the information and chunks of a Body.
Definition: app-layer-htp-body.c:94
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)
Free the information held in the request body.
Definition: app-layer-htp-body.c:122
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
StreamingBufferSegmentGetData
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
Definition: util-streaming-buffer.c:1704
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
HtpBodyChunk_::sbseg
StreamingBufferSegment sbseg
Definition: app-layer-htp.h:181
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:771
HtpBody_::body_inspected
uint64_t body_inspected
Definition: app-layer-htp.h:197