~ubuntu-branches/ubuntu/utopic/suricata/utopic

« back to all changes in this revision

Viewing changes to src/detect-engine-hcbd.c

  • Committer: Package Import Robot
  • Author(s): Pierre Chifflier
  • Date: 2012-07-22 22:27:36 UTC
  • mfrom: (1.1.13)
  • Revision ID: package-import@ubuntu.com-20120722222736-s2bcw3ruzenagjam
Tags: 1.3-1
* Imported Upstream version 1.3
* Add build-dependency on libnss3-dev and libnspr4-dev
* Bump Standards Version to 3.9.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2007-2010 Open Information Security Foundation
 
1
/* Copyright (C) 2007-2012 Open Information Security Foundation
2
2
 *
3
3
 * You can copy, redistribute or modify this Program under the terms of
4
4
 * the GNU General Public License version 2 as published by the Free
40
40
#include "detect-engine-mpm.h"
41
41
#include "detect-parse.h"
42
42
#include "detect-engine-state.h"
43
 
#include "detect-pcre.h"
44
 
#include "detect-isdataat.h"
45
 
#include "detect-bytetest.h"
46
 
#include "detect-bytejump.h"
 
43
#include "detect-engine-content-inspection.h"
47
44
 
48
45
#include "flow-util.h"
49
 
#include "util-spm.h"
50
46
#include "util-debug.h"
51
47
#include "util-print.h"
52
48
#include "flow.h"
53
 
#include "detect-flow.h"
54
 
#include "flow-var.h"
55
 
#include "threads.h"
56
 
#include "flow-alert-sid.h"
57
49
 
58
 
#include "stream-tcp.h"
59
 
#include "stream.h"
60
50
#include "app-layer-parser.h"
61
51
 
62
52
#include "util-unittest.h"
65
55
#include "app-layer-htp.h"
66
56
#include "app-layer-protos.h"
67
57
 
68
 
/**
69
 
 * \brief Run the actual payload match function for http request body.
70
 
 *
71
 
 *        For accounting the last match in relative matching the
72
 
 *        det_ctx->payload_offset int is used.
73
 
 *
74
 
 * \param de_ctx      Detection engine context.
75
 
 * \param det_ctx     Detection engine thread context.
76
 
 * \param s           Signature to inspect.
77
 
 * \param sm          SigMatch to inspect.
78
 
 * \param payload     Ptr to the request body to inspect.
79
 
 * \param payload_len Length of the request body.
80
 
 *
81
 
 * \retval 0 no match.
82
 
 * \retval 1 match.
83
 
 */
84
 
static int DoInspectHttpClientBody(DetectEngineCtx *de_ctx,
85
 
                                   DetectEngineThreadCtx *det_ctx,
86
 
                                   Signature *s, SigMatch *sm,
87
 
                                   uint8_t *payload, uint32_t payload_len)
88
 
{
89
 
    SCEnter();
90
 
 
91
 
    det_ctx->inspection_recursion_counter++;
92
 
 
93
 
    if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) {
94
 
        det_ctx->discontinue_matching = 1;
95
 
        SCReturnInt(0);
96
 
    }
97
 
 
98
 
    if (sm == NULL) {
99
 
        SCReturnInt(0);
100
 
    }
101
 
 
102
 
    if (sm->type == DETECT_AL_HTTP_CLIENT_BODY) {
103
 
        if (payload_len == 0) {
104
 
            SCReturnInt(0);
105
 
        }
106
 
 
107
 
        DetectContentData *cd = (DetectContentData *)sm->ctx;
108
 
        SCLogDebug("inspecting content %"PRIu32" payload_len %"PRIu32, cd->id, payload_len);
109
 
 
110
 
        //if (cd->flags & DETECT_CONTENT_HCBD_MPM && !(cd->flags & DETECT_CONTENT_NEGATED))
111
 
        //    goto match;
112
 
 
113
 
        /* rule parsers should take care of this */
114
 
#ifdef DEBUG
115
 
        BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
116
 
#endif
117
 
 
118
 
        /* search for our pattern, checking the matches recursively.
119
 
         * if we match we look for the next SigMatch as well */
120
 
        uint8_t *found = NULL;
121
 
        uint32_t offset = 0;
122
 
        uint32_t depth = payload_len;
123
 
        uint32_t prev_offset = 0; /**< used in recursive searching */
124
 
        uint32_t prev_payload_offset = det_ctx->payload_offset;
125
 
 
126
 
        do {
127
 
            if (cd->flags & DETECT_CONTENT_DISTANCE ||
128
 
                cd->flags & DETECT_CONTENT_WITHIN) {
129
 
                SCLogDebug("prev_payload_offset %"PRIu32, prev_payload_offset);
130
 
 
131
 
                offset = prev_payload_offset;
132
 
                depth = payload_len;
133
 
 
134
 
                if (cd->flags & DETECT_CONTENT_DISTANCE) {
135
 
                    if (cd->distance < 0 && (uint32_t)(abs(cd->distance)) > offset)
136
 
                        offset = 0;
137
 
                    else
138
 
                        offset += cd->distance;
139
 
                }
140
 
 
141
 
                if (cd->flags & DETECT_CONTENT_WITHIN) {
142
 
                    if ((int32_t)depth > (int32_t)(prev_payload_offset + cd->within + cd->distance)) {
143
 
                        depth = prev_payload_offset + cd->within + cd->distance;
144
 
                    }
145
 
                }
146
 
 
147
 
                if (cd->depth != 0) {
148
 
                    if ((cd->depth + prev_payload_offset) < depth) {
149
 
                        depth = prev_payload_offset + cd->depth;
150
 
                    }
151
 
                }
152
 
 
153
 
                if (cd->offset > offset) {
154
 
                    offset = cd->offset;
155
 
                }
156
 
            } else { /* implied no relative matches */
157
 
                /* set depth */
158
 
                if (cd->depth != 0) {
159
 
                    depth = cd->depth;
160
 
                }
161
 
 
162
 
                /* set offset */
163
 
                offset = cd->offset;
164
 
                prev_payload_offset = 0;
165
 
            }
166
 
 
167
 
            /* update offset with prev_offset if we're searching for
168
 
             * matches after the first occurence. */
169
 
            if (prev_offset != 0)
170
 
                offset = prev_offset;
171
 
 
172
 
            if (depth > payload_len)
173
 
                depth = payload_len;
174
 
 
175
 
            /* if offset is bigger than depth we can never match on a pattern.
176
 
             * We can however, "match" on a negated pattern. */
177
 
            if (offset > depth || depth == 0) {
178
 
                if (cd->flags & DETECT_CONTENT_NEGATED) {
179
 
                    goto match;
180
 
                } else {
181
 
                    SCReturnInt(0);
182
 
                }
183
 
            }
184
 
 
185
 
            uint8_t *spayload = payload + offset;
186
 
            uint32_t spayload_len = depth - offset;
187
 
            uint32_t match_offset = 0;
188
 
#ifdef DEBUG
189
 
            BUG_ON(spayload_len > payload_len);
190
 
#endif
191
 
 
192
 
            /* do the actual search with boyer moore precooked ctx */
193
 
            if (cd->flags & DETECT_CONTENT_NOCASE) {
194
 
                found = BoyerMooreNocase(cd->content, cd->content_len,
195
 
                                         spayload, spayload_len,
196
 
                                         cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
197
 
            } else {
198
 
                found = BoyerMoore(cd->content, cd->content_len,
199
 
                                   spayload, spayload_len,
200
 
                                   cd->bm_ctx->bmGs, cd->bm_ctx->bmBc);
201
 
            }
202
 
 
203
 
            /* next we evaluate the result in combination with the
204
 
             * negation flag. */
205
 
            if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
206
 
                SCReturnInt(0);
207
 
            } else if (found == NULL && cd->flags & DETECT_CONTENT_NEGATED) {
208
 
                goto match;
209
 
            } else if (found != NULL && cd->flags & DETECT_CONTENT_NEGATED) {
210
 
                det_ctx->discontinue_matching = 1;
211
 
                SCReturnInt(0);
212
 
            } else {
213
 
                match_offset = (uint32_t)((found - payload) + cd->content_len);
214
 
                det_ctx->payload_offset = match_offset;
215
 
 
216
 
                if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
217
 
                    SCLogDebug("no relative match coming up, so this is a match");
218
 
                    goto match;
219
 
                }
220
 
 
221
 
                /* bail out if we have no next match. Technically this is an
222
 
                 * error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
223
 
                 * flag set. */
224
 
                if (sm->next == NULL) {
225
 
                    SCReturnInt(0);
226
 
                }
227
 
 
228
 
                /* see if the next payload keywords match. If not, we will
229
 
                 * search for another occurence of this http client body content
230
 
                 * and see if the others match then until we run out of matches */
231
 
                int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next,
232
 
                                                payload, payload_len);
233
 
                if (r == 1) {
234
 
                    SCReturnInt(1);
235
 
                }
236
 
 
237
 
                if (det_ctx->discontinue_matching)
238
 
                    SCReturnInt(0);
239
 
 
240
 
                /* set the previous match offset to the start of this match + 1 */
241
 
                prev_offset = (match_offset - (cd->content_len - 1));
242
 
                SCLogDebug("trying to see if there is another match after "
243
 
                           "prev_offset %"PRIu32, prev_offset);
244
 
            }
245
 
 
246
 
        } while(1);
247
 
 
248
 
    } else if (sm->type == DETECT_PCRE) {
249
 
        SCLogDebug("inspecting pcre");
250
 
        DetectPcreData *pe = (DetectPcreData *)sm->ctx;
251
 
        uint32_t prev_payload_offset = det_ctx->payload_offset;
252
 
        uint32_t prev_offset = 0;
253
 
        int r = 0;
254
 
 
255
 
        det_ctx->pcre_match_start_offset = 0;
256
 
        do {
257
 
            r = DetectPcrePayloadMatch(det_ctx, s, sm, NULL, NULL,
258
 
                                       payload, payload_len);
259
 
 
260
 
            if (r == 0) {
261
 
                det_ctx->discontinue_matching = 1;
262
 
                SCReturnInt(0);
263
 
            }
264
 
 
265
 
            if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
266
 
                SCLogDebug("no relative match coming up, so this is a match");
267
 
                goto match;
268
 
            }
269
 
 
270
 
            /* save it, in case we need to do a pcre match once again */
271
 
            prev_offset = det_ctx->pcre_match_start_offset;
272
 
 
273
 
            /* see if the next payload keywords match. If not, we will
274
 
             * search for another occurence of this pcre and see
275
 
             * if the others match, until we run out of matches */
276
 
            int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next,
277
 
                                            payload, payload_len);
278
 
            if (r == 1) {
279
 
                SCReturnInt(1);
280
 
            }
281
 
 
282
 
            if (det_ctx->discontinue_matching)
283
 
                SCReturnInt(0);
284
 
 
285
 
            det_ctx->payload_offset = prev_payload_offset;
286
 
            det_ctx->pcre_match_start_offset = prev_offset;
287
 
        } while (1);
288
 
    } else {
289
 
        /* we should never get here, but bail out just in case */
290
 
        SCLogDebug("sm->type %u", sm->type);
291
 
#ifdef DEBUG
292
 
        BUG_ON(1);
293
 
#endif
294
 
    }
295
 
 
296
 
    SCReturnInt(0);
297
 
 
298
 
match:
299
 
    /* this sigmatch matched, inspect the next one. If it was the last,
300
 
     * the payload portion of the signature matched. */
301
 
    if (sm->next != NULL) {
302
 
        int r = DoInspectHttpClientBody(de_ctx, det_ctx, s, sm->next, payload,
303
 
                                        payload_len);
304
 
        SCReturnInt(r);
305
 
    } else {
306
 
        SCReturnInt(1);
307
 
    }
308
 
}
 
58
#define BODY_SCAN_WINDOW 4096
 
59
#define BODY_MINIMAL_SIZE 32768
309
60
 
310
61
/**
311
62
 * \brief Helps buffer request bodies for different transactions and stores them
316
67
 * \param f         Pointer to the flow.
317
68
 * \param htp_state http state.
318
69
 *
319
 
 * \warning Make sure flow is locked.
 
70
 * \warning Make sure flow is locked -- flow is modified, WRITE lock needed
320
71
 */
321
72
static void DetectEngineBufferHttpClientBodies(DetectEngineCtx *de_ctx,
322
 
        DetectEngineThreadCtx *det_ctx, Flow *f, HtpState *htp_state)
 
73
        DetectEngineThreadCtx *det_ctx, Flow *f, HtpState *htp_state, uint8_t flags)
323
74
{
324
75
    int idx = 0;
325
76
    htp_tx_t *tx = NULL;
326
77
    int i = 0;
327
78
 
328
 
    if (det_ctx->hcbd_buffers_list_len > 0) {
329
 
        SCReturn;
330
 
    }
331
 
 
332
79
    if (htp_state == NULL) {
333
80
        SCLogDebug("no HTTP state");
334
81
        goto end;
347
94
 
348
95
    /* let's get the transaction count.  We need this to hold the client body
349
96
     * buffer for each transaction */
350
 
    det_ctx->hcbd_buffers_list_len = list_size(htp_state->connp->conn->transactions) - tmp_idx;
 
97
    size_t txs = list_size(htp_state->connp->conn->transactions) - tmp_idx;
351
98
    /* no transactions?!  cool.  get out of here */
352
 
    if (det_ctx->hcbd_buffers_list_len == 0)
353
 
        goto end;
354
 
 
355
 
    /* assign space to hold buffers.  Each per transaction */
356
 
    det_ctx->hcbd_buffers = SCMalloc(det_ctx->hcbd_buffers_list_len * sizeof(uint8_t *));
357
 
    if (det_ctx->hcbd_buffers == NULL) {
358
 
        goto end;
359
 
    }
360
 
    memset(det_ctx->hcbd_buffers, 0, det_ctx->hcbd_buffers_list_len * sizeof(uint8_t *));
361
 
 
362
 
    det_ctx->hcbd_buffers_len = SCMalloc(det_ctx->hcbd_buffers_list_len * sizeof(uint32_t));
363
 
    if (det_ctx->hcbd_buffers_len == NULL) {
364
 
        goto end;
365
 
    }
366
 
    memset(det_ctx->hcbd_buffers_len, 0, det_ctx->hcbd_buffers_list_len * sizeof(uint32_t));
 
99
    if (txs == 0) {
 
100
        det_ctx->hcbd_buffers_list_len = 0;
 
101
        goto end;
 
102
    } else if (txs > det_ctx->hcbd_buffers_list_len) {
 
103
        det_ctx->hcbd = SCRealloc(det_ctx->hcbd, txs * sizeof(HttpReassembledBody));
 
104
        if (det_ctx->hcbd == NULL) {
 
105
            det_ctx->hcbd_buffers_list_len = 0;
 
106
            goto end;
 
107
        }
 
108
 
 
109
        memset(det_ctx->hcbd + det_ctx->hcbd_buffers_list_len, 0,
 
110
                (txs - det_ctx->hcbd_buffers_list_len) * sizeof(HttpReassembledBody));
 
111
        det_ctx->hcbd_buffers_list_len = txs;
 
112
    }
367
113
 
368
114
    idx = AppLayerTransactionGetInspectId(f);
369
115
    if (idx == -1) {
372
118
 
373
119
    int size = (int)list_size(htp_state->connp->conn->transactions);
374
120
    for (; idx < size; idx++, i++) {
 
121
        /* already set up */
 
122
        if (det_ctx->hcbd[i].buffer_len > 0) {
 
123
            SCLogDebug("set up already");
 
124
            continue;
 
125
        }
375
126
 
376
127
        tx = list_get(htp_state->connp->conn->transactions, idx);
377
 
        if (tx == NULL)
 
128
        if (tx == NULL) {
 
129
            SCLogDebug("no tx");
378
130
            continue;
 
131
        }
379
132
 
380
133
        HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
381
 
        if (htud == NULL)
382
 
            continue;
 
134
        if (htud == NULL) {
 
135
            SCLogDebug("no htud");
 
136
            continue;
 
137
        }
 
138
 
 
139
        /* no new data */
 
140
        if (htud->request_body.body_inspected == htud->request_body.content_len_so_far) {
 
141
            SCLogDebug("no new data");
 
142
            continue;
 
143
        }
383
144
 
384
145
        HtpBodyChunk *cur = htud->request_body.first;
385
 
 
386
 
        if (htud->request_body.nchunks == 0) {
 
146
        if (cur == NULL) {
387
147
            SCLogDebug("No http chunks to inspect for this transacation");
388
148
            continue;
389
 
        } else {
390
 
            /* no chunks?!! move on to the next transaction */
391
 
            if (cur == NULL) {
392
 
                SCLogDebug("No http chunks to inspect");
393
 
                continue;
394
 
            }
 
149
        }
395
150
 
396
 
            /* in case of chunked transfer encoding, we don't have the length
397
 
             * of the request body until we see a chunk with length 0.  This
398
 
             * doesn't let us use the request body callback function to
399
 
             * figure out the end of request body.  Instead we do it here.  If
400
 
             * the length is 0, and we have already seen content, it indicates
401
 
             * chunked transfer.  We also check if the parser has truly seen
402
 
             * the last chunk by checking the progress state for the
403
 
             * transaction.  If we are done parsing all the chunks, we would
404
 
             * have it set to something other than TX_PROGRESS_REQ_BODY.
405
 
             * Either ways we should be moving away from buffering in the end
406
 
             * and running content validation on this buffer type of architecture
407
 
             * to a stateful inspection, where we can inspect body chunks as and
408
 
             * when they come */
409
 
            if (htud->request_body.content_len == 0) {
410
 
                if ((htud->request_body.content_len_so_far > 0) &&
 
151
        /* in case of chunked transfer encoding, we don't have the length
 
152
         * of the request body until we see a chunk with length 0.  This
 
153
         * doesn't let us use the request body callback function to
 
154
         * figure out the end of request body.  Instead we do it here.  If
 
155
         * the length is 0, and we have already seen content, it indicates
 
156
         * chunked transfer.  We also check if the parser has truly seen
 
157
         * the last chunk by checking the progress state for the
 
158
         * transaction.  If we are done parsing all the chunks, we would
 
159
         * have it set to something other than TX_PROGRESS_REQ_BODY.
 
160
         * Either ways we should be moving away from buffering in the end
 
161
         * and running content validation on this buffer type of architecture
 
162
         * to a stateful inspection, where we can inspect body chunks as and
 
163
         * when they come */
 
164
        if (htud->request_body.content_len == 0) {
 
165
            if ((htud->request_body.content_len_so_far > 0) &&
411
166
                    tx->progress != TX_PROGRESS_REQ_BODY) {
412
 
                    /* final length of the body */
413
 
                    htud->flags |= HTP_BODY_COMPLETE;
 
167
                /* final length of the body */
 
168
                htud->tsflags |= HTP_REQ_BODY_COMPLETE;
 
169
            }
 
170
        }
 
171
 
 
172
        if (flags & STREAM_EOF) {
 
173
            htud->tsflags |= HTP_REQ_BODY_COMPLETE;
 
174
        }
 
175
 
 
176
        /* inspect the body if the transfer is complete or we have hit
 
177
         * our body size limit */
 
178
        if (htud->request_body.content_len_so_far < BODY_MINIMAL_SIZE &&
 
179
                !(htud->tsflags & HTP_REQ_BODY_COMPLETE)) {
 
180
            SCLogDebug("we still haven't seen the entire request body.  "
 
181
                    "Let's defer body inspection till we see the "
 
182
                    "entire body.");
 
183
            continue;
 
184
        }
 
185
 
 
186
        int first = 1;
 
187
        while (cur != NULL) {
 
188
            /* see if we can filter out chunks */
 
189
            if (htud->request_body.body_inspected > 0) {
 
190
                if (cur->stream_offset < htud->request_body.body_inspected) {
 
191
                    if (htud->request_body.body_inspected - cur->stream_offset > BODY_SCAN_WINDOW) {
 
192
                        cur = cur->next;
 
193
                        continue;
 
194
                    } else {
 
195
                        /* include this one */
 
196
                    }
 
197
                } else {
 
198
                    /* include this one */
414
199
                }
415
200
            }
416
201
 
417
 
            /* inspect the body if the transfer is complete or we have hit
418
 
             * our body size limit */
419
 
            if (!(htud->flags & HTP_BODY_COMPLETE)) {
420
 
                SCLogDebug("we still haven't seen the entire request body.  "
421
 
                        "Let's defer body inspection till we see the "
422
 
                        "entire body.");
423
 
                continue;
 
202
            if (first) {
 
203
                det_ctx->hcbd[i].offset = cur->stream_offset;
 
204
                first = 0;
424
205
            }
425
206
 
426
 
            uint8_t *chunks_buffer = NULL;
427
 
            int32_t chunks_buffer_len = 0;
428
 
            while (cur != NULL) {
429
 
                chunks_buffer_len += cur->len;
430
 
                if ( (chunks_buffer = SCRealloc(chunks_buffer, chunks_buffer_len)) == NULL) {
 
207
            /* see if we need to grow the buffer */
 
208
            if (det_ctx->hcbd[i].buffer == NULL || det_ctx->hcbd[i].buffer_len + cur->len > det_ctx->hcbd[i].buffer_size) {
 
209
                det_ctx->hcbd[i].buffer_size += cur->len * 2;
 
210
 
 
211
                if ((det_ctx->hcbd[i].buffer = SCRealloc(det_ctx->hcbd[i].buffer, det_ctx->hcbd[i].buffer_size)) == NULL) {
431
212
                    goto end;
432
213
                }
433
 
 
434
 
                memcpy(chunks_buffer + chunks_buffer_len - cur->len, cur->data, cur->len);
435
 
                cur = cur->next;
436
214
            }
437
 
            /* store the buffers.  We will need it for further inspection */
438
 
            det_ctx->hcbd_buffers[i] = chunks_buffer;
439
 
            det_ctx->hcbd_buffers_len[i] = chunks_buffer_len;
440
 
 
441
 
        } /* else - if (htud->body.nchunks == 0) */
 
215
            memcpy(det_ctx->hcbd[i].buffer + det_ctx->hcbd[i].buffer_len, cur->data, cur->len);
 
216
            det_ctx->hcbd[i].buffer_len += cur->len;
 
217
 
 
218
            cur = cur->next;
 
219
        }
 
220
 
 
221
        /* update inspected tracker */
 
222
        htud->request_body.body_inspected =
 
223
            htud->request_body.last->stream_offset +
 
224
            htud->request_body.last->len;
442
225
    } /* for (idx = AppLayerTransactionGetInspectId(f); .. */
443
226
 
444
227
end:
446
229
}
447
230
 
448
231
int DetectEngineRunHttpClientBodyMpm(DetectEngineCtx *de_ctx,
449
 
        DetectEngineThreadCtx *det_ctx, Flow *f, HtpState *htp_state)
 
232
                                     DetectEngineThreadCtx *det_ctx, Flow *f,
 
233
                                     HtpState *htp_state, uint8_t flags)
450
234
{
451
235
    int i;
452
236
    uint32_t cnt = 0;
453
237
 
454
 
    /* bail before locking if we have nothing to do */
455
 
    if (det_ctx->hcbd_buffers_list_len == 0) {
456
 
        SCMutexLock(&f->m);
457
 
        DetectEngineBufferHttpClientBodies(de_ctx, det_ctx, f, htp_state);
458
 
        SCMutexUnlock(&f->m);
459
 
    }
460
 
 
461
 
    for (i = 0; i < det_ctx->hcbd_buffers_list_len; i++) {
462
 
        cnt += HttpClientBodyPatternSearch(det_ctx,
463
 
                                           det_ctx->hcbd_buffers[i],
464
 
                                           det_ctx->hcbd_buffers_len[i]);
 
238
    FLOWLOCK_WRLOCK(f);
 
239
    DetectEngineBufferHttpClientBodies(de_ctx, det_ctx, f, htp_state, flags);
 
240
    FLOWLOCK_UNLOCK(f);
 
241
 
 
242
    if (det_ctx->hcbd != NULL && det_ctx->hcbd_buffers_list_len) {
 
243
        for (i = 0; i < det_ctx->hcbd_buffers_list_len; i++) {
 
244
            if (det_ctx->hcbd[i].buffer_len == 0)
 
245
                continue;
 
246
 
 
247
            cnt += HttpClientBodyPatternSearch(det_ctx,
 
248
                    det_ctx->hcbd[i].buffer,
 
249
                    det_ctx->hcbd[i].buffer_len,
 
250
                    flags);
 
251
        }
465
252
    }
466
253
 
467
254
    return cnt;
489
276
    int r = 0;
490
277
    int i = 0;
491
278
 
492
 
    /* bail before locking if we have nothing to do */
493
 
    if (det_ctx->hcbd_buffers_list_len == 0) {
494
 
        SCMutexLock(&f->m);
495
 
        DetectEngineBufferHttpClientBodies(de_ctx, det_ctx, f, alstate);
496
 
        SCMutexUnlock(&f->m);
497
 
    }
498
 
 
499
 
    for (i = 0; i < det_ctx->hcbd_buffers_list_len; i++) {
500
 
        uint8_t *hcbd_buffer = det_ctx->hcbd_buffers[i];
501
 
        uint32_t hcbd_buffer_len = det_ctx->hcbd_buffers_len[i];
502
 
 
503
 
        if (hcbd_buffer == NULL)
504
 
            continue;
505
 
 
506
 
        r = DoInspectHttpClientBody(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCBDMATCH],
507
 
                                    hcbd_buffer, hcbd_buffer_len);
508
 
        if (r == 1) {
509
 
            break;
 
279
    FLOWLOCK_WRLOCK(f);
 
280
    DetectEngineBufferHttpClientBodies(de_ctx, det_ctx, f, alstate, flags);
 
281
    FLOWLOCK_UNLOCK(f);
 
282
 
 
283
    if (det_ctx->hcbd != NULL && det_ctx->hcbd_buffers_list_len) {
 
284
        for (i = 0; i < det_ctx->hcbd_buffers_list_len; i++) {
 
285
            uint8_t *hcbd_buffer = det_ctx->hcbd[i].buffer;
 
286
            uint32_t hcbd_buffer_len = det_ctx->hcbd[i].buffer_len;
 
287
 
 
288
            if (hcbd_buffer == NULL || hcbd_buffer_len == 0)
 
289
                continue;
 
290
 
 
291
            det_ctx->buffer_offset = 0;
 
292
            det_ctx->discontinue_matching = 0;
 
293
            det_ctx->inspection_recursion_counter = 0;
 
294
 
 
295
            r = DetectEngineContentInspection(de_ctx, det_ctx, s, s->sm_lists[DETECT_SM_LIST_HCBDMATCH],
 
296
                    f,
 
297
                    hcbd_buffer,
 
298
                    hcbd_buffer_len,
 
299
                    DETECT_ENGINE_CONTENT_INSPECTION_MODE_HCBD, NULL);
 
300
            if (r == 1) {
 
301
                break;
 
302
            }
510
303
        }
511
304
    }
512
305
 
520
313
 */
521
314
void DetectEngineCleanHCBDBuffers(DetectEngineThreadCtx *det_ctx)
522
315
{
523
 
    if (det_ctx->hcbd_buffers_list_len != 0) {
524
 
        int i;
 
316
    int i;
 
317
    if (det_ctx->hcbd != NULL && det_ctx->hcbd_buffers_list_len) {
525
318
        for (i = 0; i < det_ctx->hcbd_buffers_list_len; i++) {
526
 
            if (det_ctx->hcbd_buffers[i] != NULL)
527
 
                SCFree(det_ctx->hcbd_buffers[i]);
528
 
        }
529
 
        if (det_ctx->hcbd_buffers != NULL) {
530
 
            SCFree(det_ctx->hcbd_buffers);
531
 
            det_ctx->hcbd_buffers = NULL;
532
 
        }
533
 
        if (det_ctx->hcbd_buffers_len != NULL) {
534
 
            SCFree(det_ctx->hcbd_buffers_len);
535
 
            det_ctx->hcbd_buffers_len = NULL;
536
 
        }
537
 
        det_ctx->hcbd_buffers_list_len = 0;
 
319
            det_ctx->hcbd[i].buffer_len = 0;
 
320
        }
538
321
    }
539
 
 
540
322
    return;
541
323
}
542
324
 
1292
1074
    int r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http1_buf, http1_len);
1293
1075
    if (r != 0) {
1294
1076
        printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1295
 
        result = 0;
1296
1077
        goto end;
1297
1078
    }
1298
1079
 
1299
1080
    http_state = f.alstate;
1300
1081
    if (http_state == NULL) {
1301
1082
        printf("no http state: \n");
1302
 
        result = 0;
1303
1083
        goto end;
1304
1084
    }
1305
1085
 
1314
1094
    r = AppLayerParse(NULL, &f, ALPROTO_HTTP, STREAM_TOSERVER, http2_buf, http2_len);
1315
1095
    if (r != 0) {
1316
1096
        printf("toserver chunk 1 returned %" PRId32 ", expected 0: \n", r);
1317
 
        result = 0;
1318
1097
        goto end;
1319
1098
    }
1320
1099
 
2444
2223
 
2445
2224
    /* start the search phase */
2446
2225
    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
2447
 
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
 
2226
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len, STREAM_TOSERVER);
2448
2227
    if (r != 1) {
2449
2228
        printf("expected 1 result, got %"PRIu32": ", r);
2450
2229
        goto end;
2515
2294
 
2516
2295
    /* start the search phase */
2517
2296
    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
2518
 
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
 
2297
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len, STREAM_TOSERVER);
2519
2298
    if (r != 0) {
2520
2299
        printf("expected 1 result, got %"PRIu32": ", r);
2521
2300
        goto end;
2586
2365
 
2587
2366
    /* start the search phase */
2588
2367
    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
2589
 
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
 
2368
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len, STREAM_TOSERVER);
2590
2369
    if (r != 0) {
2591
2370
        printf("expected 1 result, got %"PRIu32": ", r);
2592
2371
        goto end;
2657
2436
 
2658
2437
    /* start the search phase */
2659
2438
    det_ctx->sgh = SigMatchSignaturesGetSgh(de_ctx, det_ctx, p1);
2660
 
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len);
 
2439
    uint32_t r = HttpClientBodyPatternSearch(det_ctx, http1_buf, http1_len, STREAM_TOSERVER);
2661
2440
    if (r != 2) {
2662
2441
        printf("expected 1 result, got %"PRIu32": ", r);
2663
2442
        goto end;