Coverage Report

Created: 2025-12-31 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-engine-state.c
Line
Count
Source
1
/* Copyright (C) 2007-2021 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
 * \defgroup sigstate State support
20
 *
21
 * State is stored in the ::DetectEngineState structure. This is
22
 * basically a container for storage item of type ::DeStateStore.
23
 * They contains an array of ::DeStateStoreItem which store the
24
 * state of match for an individual signature identified by
25
 * DeStateStoreItem::sid.
26
 *
27
 * @{
28
 */
29
30
/**
31
 * \file
32
 *
33
 * \author Victor Julien <victor@inliniac.net>
34
 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
35
 *
36
 * \brief State based signature handling.
37
 */
38
39
#include "suricata-common.h"
40
41
#include "decode.h"
42
43
#include "detect.h"
44
#include "detect-engine.h"
45
#include "detect-parse.h"
46
#include "detect-engine-state.h"
47
#include "detect-engine-dcepayload.h"
48
#include "detect-engine-build.h"
49
50
#include "detect-flowvar.h"
51
52
#include "stream-tcp.h"
53
#include "stream-tcp-private.h"
54
#include "stream-tcp-reassemble.h"
55
56
#include "app-layer.h"
57
#include "app-layer-parser.h"
58
#include "app-layer-protos.h"
59
#include "app-layer-htp.h"
60
61
#include "util-unittest.h"
62
#include "util-unittest-helper.h"
63
#include "util-profiling.h"
64
65
#include "flow-util.h"
66
67
/** convert enum to string */
68
#define CASE_CODE(E)  case E: return #E
69
70
static inline int StateIsValid(uint16_t alproto, void *alstate)
71
29.1k
{
72
29.1k
    if (alstate != NULL) {
73
27.0k
        if (alproto == ALPROTO_HTTP1) {
74
2.73k
            HtpState *htp_state = (HtpState *)alstate;
75
2.73k
            if (htp_state->conn != NULL) {
76
2.73k
                return 1;
77
2.73k
            }
78
24.3k
        } else {
79
24.3k
            return 1;
80
24.3k
        }
81
27.0k
    }
82
2.05k
    return 0;
83
29.1k
}
84
85
static DeStateStore *DeStateStoreAlloc(void)
86
118k
{
87
118k
    DeStateStore *d = SCMalloc(sizeof(DeStateStore));
88
118k
    if (unlikely(d == NULL))
89
0
        return NULL;
90
118k
    memset(d, 0, sizeof(DeStateStore));
91
92
118k
    return d;
93
118k
}
94
95
#ifdef DEBUG_VALIDATION
96
static int DeStateSearchState(DetectEngineState *state, uint8_t direction, SigIntId num)
97
136k
{
98
136k
    DetectEngineStateDirection *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1];
99
136k
    DeStateStore *tx_store = dir_state->head;
100
136k
    SigIntId store_cnt;
101
136k
    SigIntId state_cnt = 0;
102
103
153k
    for (; tx_store != NULL; tx_store = tx_store->next) {
104
17.5k
        SCLogDebug("tx_store %p", tx_store);
105
17.5k
        for (store_cnt = 0;
106
45.7k
             store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < dir_state->cnt;
107
28.1k
             store_cnt++, state_cnt++)
108
28.1k
        {
109
28.1k
            DeStateStoreItem *item = &tx_store->store[store_cnt];
110
28.1k
            if (item->sid == num) {
111
0
                SCLogDebug("sid %u already in state: %p %p %p %u %u, direction %s",
112
0
                            num, state, dir_state, tx_store, state_cnt,
113
0
                            store_cnt, direction & STREAM_TOSERVER ? "toserver" : "toclient");
114
0
                return 1;
115
0
            }
116
28.1k
        }
117
17.5k
    }
118
136k
    return 0;
119
136k
}
120
#endif
121
122
static void DeStateSignatureAppend(DetectEngineState *state,
123
        const Signature *s, uint32_t inspect_flags, uint8_t direction)
124
136k
{
125
136k
    SCEnter();
126
127
136k
    DetectEngineStateDirection *dir_state =
128
136k
            &state->dir_state[(direction & STREAM_TOSERVER) ? 0 : 1];
129
130
136k
#ifdef DEBUG_VALIDATION
131
136k
    BUG_ON(DeStateSearchState(state, direction, s->num));
132
136k
#endif
133
136k
    DeStateStore *store = dir_state->tail;
134
136k
    if (store == NULL) {
135
118k
        store = DeStateStoreAlloc();
136
118k
        dir_state->head = store;
137
118k
        dir_state->cur = store;
138
118k
        dir_state->tail = store;
139
118k
    } else if (dir_state->cur) {
140
17.5k
        store = dir_state->cur;
141
17.5k
    } else {
142
0
        store = DeStateStoreAlloc();
143
0
        if (store != NULL) {
144
0
            dir_state->tail->next = store;
145
0
            dir_state->tail = store;
146
0
            dir_state->cur = store;
147
0
        }
148
0
    }
149
136k
    if (store == NULL)
150
0
        SCReturn;
151
152
136k
    SigIntId idx = dir_state->cnt % DE_STATE_CHUNK_SIZE;
153
136k
    store->store[idx].sid = s->num;
154
136k
    store->store[idx].flags = inspect_flags;
155
136k
    dir_state->cnt++;
156
    /* if current chunk is full, progress cur */
157
136k
    if (dir_state->cnt % DE_STATE_CHUNK_SIZE == 0) {
158
0
        dir_state->cur = dir_state->cur->next;
159
0
    }
160
161
136k
    SCReturn;
162
136k
}
163
164
DetectEngineState *DetectEngineStateAlloc(void)
165
91.7k
{
166
91.7k
    DetectEngineState *d = SCMalloc(sizeof(DetectEngineState));
167
91.7k
    if (unlikely(d == NULL))
168
0
        return NULL;
169
91.7k
    memset(d, 0, sizeof(DetectEngineState));
170
171
91.7k
    return d;
172
91.7k
}
173
174
void DetectEngineStateFree(DetectEngineState *state)
175
44.3k
{
176
44.3k
    DeStateStore *store;
177
44.3k
    DeStateStore *store_next;
178
44.3k
    int i = 0;
179
180
133k
    for (i = 0; i < 2; i++) {
181
88.7k
        store = state->dir_state[i].head;
182
145k
        while (store != NULL) {
183
56.7k
            store_next = store->next;
184
56.7k
            SCFree(store);
185
56.7k
            store = store_next;
186
56.7k
        }
187
88.7k
    }
188
44.3k
    SCFree(state);
189
190
44.3k
    return;
191
44.3k
}
192
193
static void StoreFileNoMatchCnt(DetectEngineState *de_state, uint16_t file_no_match, uint8_t direction)
194
63.3k
{
195
63.3k
    de_state->dir_state[(direction & STREAM_TOSERVER) ? 0 : 1].filestore_cnt += file_no_match;
196
197
63.3k
    return;
198
63.3k
}
199
200
static bool StoreFilestoreSigsCantMatch(const SigGroupHead *sgh, const DetectEngineState *de_state, uint8_t direction)
201
136k
{
202
136k
    if (de_state->dir_state[(direction & STREAM_TOSERVER) ? 0 : 1].filestore_cnt ==
203
136k
            sgh->filestore_cnt)
204
66.8k
        return true;
205
69.2k
    else
206
69.2k
        return false;
207
136k
}
208
209
static void StoreStateTxHandleFiles(const SigGroupHead *sgh, Flow *f, DetectEngineState *destate,
210
        const uint8_t flow_flags, void *tx, const uint64_t tx_id, const uint16_t file_no_match)
211
136k
{
212
136k
    SCLogDebug("tx %"PRIu64", file_no_match %u", tx_id, file_no_match);
213
136k
    StoreFileNoMatchCnt(destate, file_no_match, flow_flags);
214
136k
    if (StoreFilestoreSigsCantMatch(sgh, destate, flow_flags)) {
215
66.8k
        SCLogDebug("filestore sigs can't match");
216
66.8k
        FileDisableStoringForTransaction(
217
66.8k
                f, flow_flags & (STREAM_TOCLIENT | STREAM_TOSERVER), tx, tx_id);
218
69.2k
    } else {
219
69.2k
        SCLogDebug("filestore sigs can still match");
220
69.2k
    }
221
136k
}
222
223
void DetectRunStoreStateTx(
224
        const SigGroupHead *sgh,
225
        Flow *f, void *tx, uint64_t tx_id,
226
        const Signature *s,
227
        uint32_t inspect_flags, uint8_t flow_flags,
228
        const uint16_t file_no_match)
229
63.3k
{
230
63.3k
    AppLayerTxData *tx_data = AppLayerParserGetTxData(f->proto, f->alproto, tx);
231
63.3k
    if (tx_data == NULL) {
232
0
        SCLogDebug("No TX data for %" PRIu64, tx_id);
233
0
        return;
234
0
    }
235
63.3k
    if (tx_data->de_state == NULL) {
236
44.3k
        tx_data->de_state = DetectEngineStateAlloc();
237
44.3k
        if (tx_data->de_state == NULL)
238
0
            return;
239
44.3k
        SCLogDebug("destate created for %"PRIu64, tx_id);
240
44.3k
    }
241
63.3k
    DeStateSignatureAppend(tx_data->de_state, s, inspect_flags, flow_flags);
242
63.3k
    StoreStateTxHandleFiles(sgh, f, tx_data->de_state, flow_flags, tx, tx_id, file_no_match);
243
244
63.3k
    SCLogDebug("Stored for TX %"PRIu64, tx_id);
245
63.3k
}
246
247
static inline void ResetTxState(DetectEngineState *s)
248
15.9k
{
249
15.9k
    if (s) {
250
0
        s->dir_state[0].cnt = 0;
251
0
        s->dir_state[0].filestore_cnt = 0;
252
0
        s->dir_state[0].flags = 0;
253
        /* reset 'cur' back to the list head */
254
0
        s->dir_state[0].cur = s->dir_state[0].head;
255
256
0
        s->dir_state[1].cnt = 0;
257
0
        s->dir_state[1].filestore_cnt = 0;
258
0
        s->dir_state[1].flags = 0;
259
        /* reset 'cur' back to the list head */
260
0
        s->dir_state[1].cur = s->dir_state[1].head;
261
0
    }
262
15.9k
}
263
264
/** \brief Reset de state for active tx'
265
 *  To be used on detect engine reload.
266
 *  \param f write LOCKED flow
267
 */
268
void DetectEngineStateResetTxs(Flow *f)
269
15.1k
{
270
15.1k
    void *alstate = FlowGetAppState(f);
271
15.1k
    if (!StateIsValid(f->alproto, alstate)) {
272
1.28k
        return;
273
1.28k
    }
274
275
13.8k
    uint64_t inspect_ts = AppLayerParserGetTransactionInspectId(f->alparser, STREAM_TOCLIENT);
276
13.8k
    uint64_t inspect_tc = AppLayerParserGetTransactionInspectId(f->alparser, STREAM_TOSERVER);
277
278
13.8k
    uint64_t inspect_tx_id = MIN(inspect_ts, inspect_tc);
279
280
13.8k
    uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
281
282
17.6k
    for ( ; inspect_tx_id < total_txs; inspect_tx_id++) {
283
3.84k
        void *inspect_tx = AppLayerParserGetTx(f->proto, f->alproto, alstate, inspect_tx_id);
284
3.84k
        if (inspect_tx != NULL) {
285
3.84k
            AppLayerTxData *txd = AppLayerParserGetTxData(f->proto, f->alproto, inspect_tx);
286
3.84k
            if (txd) {
287
3.84k
                ResetTxState(txd->de_state);
288
3.84k
            }
289
3.84k
        }
290
3.84k
    }
291
13.8k
}
292
293
/*********Unittests*********/
294
295
#ifdef UNITTESTS
296
#include "detect-engine-alert.h"
297
298
static int DeStateTest01(void)
299
{
300
    SCLogDebug("sizeof(DetectEngineState)\t\t%"PRIuMAX,
301
            (uintmax_t)sizeof(DetectEngineState));
302
    SCLogDebug("sizeof(DeStateStore)\t\t\t%"PRIuMAX,
303
            (uintmax_t)sizeof(DeStateStore));
304
    SCLogDebug("sizeof(DeStateStoreItem)\t\t%"PRIuMAX"",
305
            (uintmax_t)sizeof(DeStateStoreItem));
306
307
    return 1;
308
}
309
310
static int DeStateTest02(void)
311
{
312
    uint8_t direction = STREAM_TOSERVER;
313
    DetectEngineState *state = DetectEngineStateAlloc();
314
    FAIL_IF_NULL(state);
315
    FAIL_IF_NOT_NULL(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head);
316
317
    Signature s;
318
    memset(&s, 0x00, sizeof(s));
319
320
    s.num = 0;
321
    DeStateSignatureAppend(state, &s, 0, direction);
322
    s.num = 11;
323
    DeStateSignatureAppend(state, &s, 0, direction);
324
    s.num = 22;
325
    DeStateSignatureAppend(state, &s, 0, direction);
326
    s.num = 33;
327
    DeStateSignatureAppend(state, &s, 0, direction);
328
    s.num = 44;
329
    DeStateSignatureAppend(state, &s, 0, direction);
330
    s.num = 55;
331
    DeStateSignatureAppend(state, &s, 0, direction);
332
    s.num = 66;
333
    DeStateSignatureAppend(state, &s, 0, direction);
334
    s.num = 77;
335
    DeStateSignatureAppend(state, &s, 0, direction);
336
    s.num = 88;
337
    DeStateSignatureAppend(state, &s, 0, direction);
338
    s.num = 99;
339
    DeStateSignatureAppend(state, &s, 0, direction);
340
    s.num = 100;
341
    DeStateSignatureAppend(state, &s, 0, direction);
342
    s.num = 111;
343
    DeStateSignatureAppend(state, &s, 0, direction);
344
    s.num = 122;
345
    DeStateSignatureAppend(state, &s, 0, direction);
346
    s.num = 133;
347
    DeStateSignatureAppend(state, &s, 0, direction);
348
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
349
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
350
351
    s.num = 144;
352
    DeStateSignatureAppend(state, &s, 0, direction);
353
354
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
355
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
356
            state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
357
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur == NULL);
358
359
    s.num = 155;
360
    DeStateSignatureAppend(state, &s, 0, direction);
361
362
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].tail ==
363
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
364
365
    s.num = 166;
366
    DeStateSignatureAppend(state, &s, 0, direction);
367
368
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
369
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11);
370
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL);
371
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
372
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155);
373
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166);
374
375
    ResetTxState(state);
376
377
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
378
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
379
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
380
381
    s.num = 0;
382
    DeStateSignatureAppend(state, &s, 0, direction);
383
    s.num = 11;
384
    DeStateSignatureAppend(state, &s, 0, direction);
385
    s.num = 22;
386
    DeStateSignatureAppend(state, &s, 0, direction);
387
    s.num = 33;
388
    DeStateSignatureAppend(state, &s, 0, direction);
389
    s.num = 44;
390
    DeStateSignatureAppend(state, &s, 0, direction);
391
    s.num = 55;
392
    DeStateSignatureAppend(state, &s, 0, direction);
393
    s.num = 66;
394
    DeStateSignatureAppend(state, &s, 0, direction);
395
    s.num = 77;
396
    DeStateSignatureAppend(state, &s, 0, direction);
397
    s.num = 88;
398
    DeStateSignatureAppend(state, &s, 0, direction);
399
    s.num = 99;
400
    DeStateSignatureAppend(state, &s, 0, direction);
401
    s.num = 100;
402
    DeStateSignatureAppend(state, &s, 0, direction);
403
    s.num = 111;
404
    DeStateSignatureAppend(state, &s, 0, direction);
405
    s.num = 122;
406
    DeStateSignatureAppend(state, &s, 0, direction);
407
    s.num = 133;
408
    DeStateSignatureAppend(state, &s, 0, direction);
409
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
410
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
411
    s.num = 144;
412
    DeStateSignatureAppend(state, &s, 0, direction);
413
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
414
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
415
            state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
416
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].tail ==
417
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
418
    s.num = 155;
419
    DeStateSignatureAppend(state, &s, 0, direction);
420
    s.num = 166;
421
    DeStateSignatureAppend(state, &s, 0, direction);
422
423
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
424
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11);
425
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL);
426
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
427
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155);
428
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166);
429
430
    DetectEngineStateFree(state);
431
432
    PASS;
433
}
434
435
static int DeStateTest03(void)
436
{
437
    DetectEngineState *state = DetectEngineStateAlloc();
438
    FAIL_IF_NULL(state);
439
440
    Signature s;
441
    memset(&s, 0x00, sizeof(s));
442
443
    uint8_t direction = STREAM_TOSERVER;
444
445
    s.num = 11;
446
    DeStateSignatureAppend(state, &s, 0, direction);
447
    s.num = 22;
448
    DeStateSignatureAppend(state, &s, BIT_U32(DE_STATE_FLAG_BASE), direction);
449
450
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
451
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].sid != 11);
452
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].flags & BIT_U32(DE_STATE_FLAG_BASE));
453
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 22);
454
    FAIL_IF(!(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].flags & BIT_U32(DE_STATE_FLAG_BASE)));
455
456
    DetectEngineStateFree(state);
457
    PASS;
458
}
459
460
static int DeStateSigTest01(void)
461
{
462
    DetectEngineThreadCtx *det_ctx = NULL;
463
    ThreadVars th_v;
464
    Flow f;
465
    TcpSession ssn;
466
    Packet *p = NULL;
467
    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\n";
468
    uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\n";
469
    uint8_t httpbuf3[] = "Cookie: dummy\r\nContent-Length: 10\r\n\r\n";
470
    uint8_t httpbuf4[] = "Http Body!";
471
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
472
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
473
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
474
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
475
476
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
477
    FAIL_IF_NULL(alp_tctx);
478
479
    memset(&th_v, 0, sizeof(th_v));
480
    memset(&f, 0, sizeof(f));
481
    memset(&ssn, 0, sizeof(ssn));
482
483
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
484
    FAIL_IF_NULL(p);
485
486
    FLOW_INITIALIZE(&f);
487
    f.protoctx = (void *)&ssn;
488
    f.proto = IPPROTO_TCP;
489
    f.flags |= FLOW_IPV4;
490
    f.alproto = ALPROTO_HTTP1;
491
492
    p->flow = &f;
493
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
494
    p->flowflags |= FLOW_PKT_TOSERVER;
495
    p->flowflags |= FLOW_PKT_ESTABLISHED;
496
497
    StreamTcpInitConfig(true);
498
499
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
500
    FAIL_IF_NULL(de_ctx);
501
    de_ctx->flags |= DE_QUIET;
502
503
    Signature *s = de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"dummy\"; http_cookie; sid:1; rev:1;)");
504
    FAIL_IF_NULL(s);
505
506
    SigGroupBuild(de_ctx);
507
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
508
    FAIL_IF_NULL(det_ctx);
509
510
    int r = AppLayerParserParse(
511
            NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
512
    FAIL_IF_NOT(r == 0);
513
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
514
    FAIL_IF(PacketAlertCheck(p, 1));
515
516
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
517
    FAIL_IF_NOT(r == 0);
518
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
519
    FAIL_IF(PacketAlertCheck(p, 1));
520
521
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
522
    FAIL_IF_NOT(r == 0);
523
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
524
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
525
526
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
527
    FAIL_IF_NOT(r == 0);
528
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
529
    FAIL_IF(PacketAlertCheck(p, 1));
530
531
    AppLayerParserThreadCtxFree(alp_tctx);
532
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
533
    DetectEngineCtxFree(de_ctx);
534
    StreamTcpFreeConfig(true);
535
    FLOW_DESTROY(&f);
536
    UTHFreePacket(p);
537
    PASS;
538
}
539
540
/** \test multiple pipelined http transactions */
541
static int DeStateSigTest02(void)
542
{
543
    DetectEngineThreadCtx *det_ctx = NULL;
544
    ThreadVars th_v;
545
    Flow f;
546
    TcpSession ssn;
547
    Packet *p = NULL;
548
    uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
549
    uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
550
    uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
551
    uint8_t httpbuf4[] = "Http Body!";
552
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
553
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
554
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
555
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
556
    uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
557
    uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
558
    uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nHttp Body!";
559
    uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
560
    uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
561
    uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
562
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
563
    FAIL_IF_NULL(alp_tctx);
564
565
    memset(&th_v, 0, sizeof(th_v));
566
    memset(&f, 0, sizeof(f));
567
    memset(&ssn, 0, sizeof(ssn));
568
569
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
570
571
    FLOW_INITIALIZE(&f);
572
    f.protoctx = (void *)&ssn;
573
    f.proto = IPPROTO_TCP;
574
    f.flags |= FLOW_IPV4;
575
576
    p->flow = &f;
577
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
578
    p->flowflags |= FLOW_PKT_TOSERVER;
579
    p->flowflags |= FLOW_PKT_ESTABLISHED;
580
    f.alproto = ALPROTO_HTTP1;
581
582
    StreamTcpInitConfig(true);
583
584
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
585
    FAIL_IF_NULL(de_ctx);
586
587
    de_ctx->flags |= DE_QUIET;
588
589
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:to_server; content:\"POST\"; http_method; content:\"/\"; http_uri; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"body\"; nocase; http_client_body; sid:1; rev:1;)");
590
    FAIL_IF_NULL(s);
591
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (flow:to_server; content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; sid:2; rev:1;)");
592
    FAIL_IF_NULL(s);
593
594
    SigGroupBuild(de_ctx);
595
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
596
    FAIL_IF_NULL(det_ctx);
597
598
    int r = AppLayerParserParse(
599
            NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
600
    FAIL_IF(r != 0);
601
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
602
    FAIL_IF(PacketAlertCheck(p, 1));
603
604
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
605
    FAIL_IF(r != 0);
606
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
607
    FAIL_IF(PacketAlertCheck(p, 1));
608
609
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
610
    FAIL_IF(r != 0);
611
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
612
    FAIL_IF(PacketAlertCheck(p, 1));
613
614
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f.alstate, 0);
615
    FAIL_IF_NULL(tx);
616
617
    AppLayerTxData *tx_data = AppLayerParserGetTxData(IPPROTO_TCP, ALPROTO_HTTP1, tx);
618
    FAIL_IF_NULL(tx_data);
619
    DetectEngineState *tx_de_state = tx_data->de_state;
620
    FAIL_IF_NULL(tx_de_state);
621
    FAIL_IF(tx_de_state->dir_state[0].cnt != 1);
622
    /* http_header(mpm): 5, uri: 3, method: 6, cookie: 7 */
623
    uint32_t expected_flags = (BIT_U32(5) | BIT_U32(3) | BIT_U32(6) | BIT_U32(4));
624
    FAIL_IF(tx_de_state->dir_state[0].head->store[0].flags != expected_flags);
625
626
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
627
    FAIL_IF(r != 0);
628
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
629
    FAIL_IF(!(PacketAlertCheck(p, 1)));
630
631
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
632
    FAIL_IF(r != 0);
633
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
634
    FAIL_IF(PacketAlertCheck(p, 1));
635
636
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
637
    FAIL_IF(r != 0);
638
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
639
    FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
640
641
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
642
    FAIL_IF(r != 0);
643
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
644
    FAIL_IF(!(PacketAlertCheck(p, 2)));
645
646
    AppLayerParserThreadCtxFree(alp_tctx);
647
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
648
    DetectEngineCtxFree(de_ctx);
649
    StreamTcpFreeConfig(true);
650
    FLOW_DESTROY(&f);
651
    UTHFreePacket(p);
652
    PASS;
653
}
654
655
static int DeStateSigTest03(void)
656
{
657
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
658
                         "Host: www.server.lan\r\n"
659
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
660
                         "Content-Length: 215\r\n"
661
                         "\r\n"
662
                         "-----------------------------277531038314945\r\n"
663
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
664
                         "Content-Type: image/jpeg\r\n"
665
                         "\r\n"
666
                         "filecontent\r\n"
667
                         "-----------------------------277531038314945--";
668
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
669
    ThreadVars th_v;
670
    TcpSession ssn;
671
    Flow *f = NULL;
672
    Packet *p = NULL;
673
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
674
    FAIL_IF_NULL(alp_tctx);
675
676
    memset(&th_v, 0, sizeof(th_v));
677
    memset(&ssn, 0, sizeof(ssn));
678
679
    DetectEngineThreadCtx *det_ctx = NULL;
680
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
681
    FAIL_IF_NULL(de_ctx);
682
683
    de_ctx->flags |= DE_QUIET;
684
685
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (flow:to_server; content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)");
686
    FAIL_IF_NULL(s);
687
688
    SigGroupBuild(de_ctx);
689
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
690
691
    f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
692
    FAIL_IF_NULL(f);
693
    f->protoctx = &ssn;
694
    f->proto = IPPROTO_TCP;
695
    f->alproto = ALPROTO_HTTP1;
696
697
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
698
    FAIL_IF_NULL(p);
699
700
    p->flow = f;
701
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
702
    p->flowflags |= FLOW_PKT_TOSERVER;
703
    p->flowflags |= FLOW_PKT_ESTABLISHED;
704
705
    StreamTcpInitConfig(true);
706
707
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
708
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
709
    FAIL_IF(r != 0);
710
711
    HtpState *http_state = f->alstate;
712
    FAIL_IF_NULL(http_state);
713
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
714
    FAIL_IF_NULL(tx);
715
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
716
    FAIL_IF_NULL(tx_ud);
717
718
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
719
    FAIL_IF(!(PacketAlertCheck(p, 1)));
720
721
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
722
    FileContainer *fc = files.fc;
723
    FAIL_IF_NULL(fc);
724
725
    File *file = fc->head;
726
    FAIL_IF_NULL(file);
727
728
    FAIL_IF(!(file->flags & FILE_STORE));
729
730
    AppLayerParserThreadCtxFree(alp_tctx);
731
    UTHFreeFlow(f);
732
733
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
734
    DetectEngineCtxFree(de_ctx);
735
    StreamTcpFreeConfig(true);
736
    PASS;
737
}
738
739
static int DeStateSigTest04(void)
740
{
741
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
742
                         "Host: www.server.lan\r\n"
743
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
744
                         "Content-Length: 215\r\n"
745
                         "\r\n"
746
                         "-----------------------------277531038314945\r\n"
747
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
748
                         "Content-Type: image/jpeg\r\n"
749
                         "\r\n"
750
                         "filecontent\r\n"
751
                         "-----------------------------277531038314945--";
752
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
753
    ThreadVars th_v;
754
    TcpSession ssn;
755
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
756
    FAIL_IF_NULL(alp_tctx);
757
758
    memset(&th_v, 0, sizeof(th_v));
759
    memset(&ssn, 0, sizeof(ssn));
760
761
    DetectEngineThreadCtx *det_ctx = NULL;
762
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
763
    FAIL_IF_NULL(de_ctx);
764
    de_ctx->flags |= DE_QUIET;
765
766
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)");
767
    FAIL_IF_NULL(s);
768
769
    SigGroupBuild(de_ctx);
770
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
771
    FAIL_IF_NULL(det_ctx);
772
773
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
774
    FAIL_IF_NULL(f);
775
    f->protoctx = &ssn;
776
    f->proto = IPPROTO_TCP;
777
    f->alproto = ALPROTO_HTTP1;
778
779
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
780
    FAIL_IF_NULL(p);
781
    p->flow = f;
782
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
783
    p->flowflags |= FLOW_PKT_TOSERVER;
784
    p->flowflags |= FLOW_PKT_ESTABLISHED;
785
786
    StreamTcpInitConfig(true);
787
788
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
789
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
790
    FAIL_IF(r != 0);
791
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
792
    FAIL_IF(PacketAlertCheck(p, 1));
793
794
    HtpState *http_state = f->alstate;
795
    FAIL_IF_NULL(http_state);
796
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
797
    FAIL_IF_NULL(tx);
798
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
799
    FAIL_IF_NULL(tx_ud);
800
801
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
802
    FileContainer *fc = files.fc;
803
    FAIL_IF_NULL(fc);
804
    File *file = fc->head;
805
    FAIL_IF_NULL(file);
806
807
    FAIL_IF(file->flags & FILE_STORE);
808
809
    AppLayerParserThreadCtxFree(alp_tctx);
810
    UTHFreeFlow(f);
811
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
812
    DetectEngineCtxFree(de_ctx);
813
    StreamTcpFreeConfig(true);
814
    PASS;
815
}
816
817
static int DeStateSigTest05(void)
818
{
819
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
820
                         "Host: www.server.lan\r\n"
821
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
822
                         "Content-Length: 215\r\n"
823
                         "\r\n"
824
                         "-----------------------------277531038314945\r\n"
825
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
826
                         "Content-Type: image/jpeg\r\n"
827
                         "\r\n"
828
                         "filecontent\r\n"
829
                         "-----------------------------277531038314945--";
830
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
831
    ThreadVars th_v;
832
    TcpSession ssn;
833
834
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
835
    FAIL_IF_NULL(alp_tctx);
836
837
    memset(&th_v, 0, sizeof(th_v));
838
    memset(&ssn, 0, sizeof(ssn));
839
840
    DetectEngineThreadCtx *det_ctx = NULL;
841
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
842
    FAIL_IF_NULL(de_ctx);
843
    de_ctx->flags |= DE_QUIET;
844
845
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"nomatch\"; sid:1; rev:1;)");
846
    FAIL_IF_NULL(s);
847
848
    SigGroupBuild(de_ctx);
849
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
850
851
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
852
    FAIL_IF_NULL(f);
853
    f->protoctx = &ssn;
854
    f->proto = IPPROTO_TCP;
855
    f->alproto = ALPROTO_HTTP1;
856
857
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
858
    FAIL_IF_NULL(p);
859
    p->flow = f;
860
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
861
    p->flowflags |= FLOW_PKT_TOSERVER;
862
    p->flowflags |= FLOW_PKT_ESTABLISHED;
863
864
    StreamTcpInitConfig(true);
865
866
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
867
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
868
    FAIL_IF_NOT(r == 0);
869
    HtpState *http_state = f->alstate;
870
    FAIL_IF_NULL(http_state);
871
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
872
    FAIL_IF_NULL(tx);
873
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
874
    FAIL_IF_NULL(tx_ud);
875
876
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
877
    FileContainer *fc = files.fc;
878
    FAIL_IF_NULL(fc);
879
    File *file = fc->head;
880
    FAIL_IF_NULL(file);
881
    FAIL_IF(http_state->state_data.file_flags & FLOWFILE_NO_STORE_TS);
882
883
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
884
    FAIL_IF(PacketAlertCheck(p, 1));
885
886
    /* detect will have set FLOWFILE_NO_STORE_TS, but it won't have had
887
     * an opportunity to be applied to the file itself yet */
888
    FAIL_IF_NOT(http_state->state_data.file_flags & FLOWFILE_NO_STORE_TS);
889
    FAIL_IF(file->flags & FILE_NOSTORE);
890
891
    AppLayerParserThreadCtxFree(alp_tctx);
892
    UTHFreeFlow(f);
893
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
894
    DetectEngineCtxFree(de_ctx);
895
    StreamTcpFreeConfig(true);
896
    PASS;
897
}
898
899
static int DeStateSigTest06(void)
900
{
901
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
902
                         "Host: www.server.lan\r\n"
903
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
904
                         "Content-Length: 215\r\n"
905
                         "\r\n"
906
                         "-----------------------------277531038314945\r\n"
907
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
908
                         "Content-Type: image/jpeg\r\n"
909
                         "\r\n"
910
                         "filecontent\r\n"
911
                         "-----------------------------277531038314945--";
912
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
913
    ThreadVars th_v;
914
    TcpSession ssn;
915
916
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
917
    FAIL_IF_NULL(alp_tctx);
918
919
    memset(&th_v, 0, sizeof(th_v));
920
    memset(&ssn, 0, sizeof(ssn));
921
922
    DetectEngineThreadCtx *det_ctx = NULL;
923
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
924
    FAIL_IF_NULL(de_ctx);
925
    de_ctx->flags |= DE_QUIET;
926
927
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"nomatch\"; filestore; sid:1; rev:1;)");
928
    FAIL_IF_NULL(s);
929
930
    SigGroupBuild(de_ctx);
931
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
932
    FAIL_IF_NULL(det_ctx);
933
934
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
935
    FAIL_IF_NULL(f);
936
    f->protoctx = &ssn;
937
    f->proto = IPPROTO_TCP;
938
    f->alproto = ALPROTO_HTTP1;
939
940
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
941
    FAIL_IF_NULL(p);
942
    p->flow = f;
943
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
944
    p->flowflags |= FLOW_PKT_TOSERVER;
945
    p->flowflags |= FLOW_PKT_ESTABLISHED;
946
947
    StreamTcpInitConfig(true);
948
949
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
950
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
951
    FAIL_IF(r != 0);
952
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
953
    FAIL_IF(PacketAlertCheck(p, 1));
954
955
    HtpState *http_state = f->alstate;
956
    FAIL_IF_NULL(http_state);
957
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
958
    FAIL_IF_NULL(tx);
959
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
960
    FAIL_IF_NULL(tx_ud);
961
962
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
963
    FileContainer *fc = files.fc;
964
    FAIL_IF_NULL(fc);
965
    File *file = fc->head;
966
    FAIL_IF_NULL(file);
967
    /* detect will have set FLOWFILE_NO_STORE_TS, but it won't have had
968
     * an opportunity to be applied to the file itself yet */
969
    FAIL_IF_NOT(tx_ud->tx_data.file_flags & FLOWFILE_NO_STORE_TS);
970
    FAIL_IF(file->flags & FILE_NOSTORE);
971
972
    AppLayerParserThreadCtxFree(alp_tctx);
973
    UTHFreeFlow(f);
974
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
975
    DetectEngineCtxFree(de_ctx);
976
    StreamTcpFreeConfig(true);
977
    PASS;
978
}
979
980
static int DeStateSigTest07(void)
981
{
982
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
983
                         "Host: www.server.lan\r\n"
984
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
985
                         "Content-Length: 215\r\n"
986
                         "\r\n"
987
                         "-----------------------------277531038314945\r\n"
988
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
989
                         "Content-Type: image/jpeg\r\n"
990
                         "\r\n";
991
992
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
993
    uint8_t httpbuf2[] = "filecontent\r\n"
994
                         "-----------------------------277531038314945--";
995
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
996
    ThreadVars th_v;
997
    TcpSession ssn;
998
999
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1000
    FAIL_IF_NULL(alp_tctx);
1001
1002
    memset(&th_v, 0, sizeof(th_v));
1003
    memset(&ssn, 0, sizeof(ssn));
1004
1005
    DetectEngineThreadCtx *det_ctx = NULL;
1006
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1007
    FAIL_IF_NULL(de_ctx);
1008
    de_ctx->flags |= DE_QUIET;
1009
1010
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"GET\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)");
1011
    FAIL_IF_NULL(s);
1012
1013
    SigGroupBuild(de_ctx);
1014
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1015
1016
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1017
    FAIL_IF_NULL(f);
1018
    f->protoctx = &ssn;
1019
    f->proto = IPPROTO_TCP;
1020
    f->alproto = ALPROTO_HTTP1;
1021
1022
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1023
    FAIL_IF_NULL(p);
1024
    p->flow = f;
1025
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1026
    p->flowflags |= FLOW_PKT_TOSERVER;
1027
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1028
1029
    StreamTcpInitConfig(true);
1030
1031
    int r = AppLayerParserParse(
1032
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1033
    FAIL_IF(r != 0);
1034
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1035
    FAIL_IF(PacketAlertCheck(p, 1));
1036
1037
    r = AppLayerParserParse(
1038
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1039
    FAIL_IF(r != 0);
1040
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1041
    FAIL_IF(PacketAlertCheck(p, 1));
1042
1043
    HtpState *http_state = f->alstate;
1044
    FAIL_IF_NULL(http_state);
1045
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1046
    FAIL_IF_NULL(tx);
1047
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1048
    FAIL_IF_NULL(tx_ud);
1049
1050
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
1051
    FileContainer *fc = files.fc;
1052
    FAIL_IF_NULL(fc);
1053
    File *file = fc->head;
1054
    FAIL_IF_NULL(file);
1055
    FAIL_IF(file->flags & FILE_STORE);
1056
1057
    AppLayerParserThreadCtxFree(alp_tctx);
1058
    UTHFreeFlow(f);
1059
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1060
    DetectEngineCtxFree(de_ctx);
1061
    StreamTcpFreeConfig(true);
1062
    PASS;
1063
}
1064
1065
/**
1066
 * \test multiple files in a tx
1067
 */
1068
static int DeStateSigTest08(void)
1069
{
1070
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1071
                         "Host: www.server.lan\r\n"
1072
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1073
                         "Content-Length: 440\r\n"
1074
                         "\r\n"
1075
                         "-----------------------------277531038314945\r\n"
1076
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"AAAApicture1.jpg\"\r\n"
1077
                         "Content-Type: image/jpeg\r\n"
1078
                         "\r\n";
1079
1080
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1081
    uint8_t httpbuf2[] = "file";
1082
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1083
    uint8_t httpbuf3[] = "content\r\n"
1084
                         "-----------------------------277531038314945\r\n";
1085
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1086
1087
    uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"BBBBpicture2.jpg\"\r\n"
1088
                         "Content-Type: image/jpeg\r\n"
1089
                         "\r\n"
1090
                         "filecontent2\r\n"
1091
                         "-----------------------------277531038314945--";
1092
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1093
1094
    ThreadVars th_v;
1095
    TcpSession ssn;
1096
1097
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1098
    FAIL_IF_NULL(alp_tctx);
1099
1100
    memset(&th_v, 0, sizeof(th_v));
1101
    memset(&ssn, 0, sizeof(ssn));
1102
1103
    DetectEngineThreadCtx *det_ctx = NULL;
1104
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1105
    FAIL_IF_NULL(de_ctx);
1106
    de_ctx->flags |= DE_QUIET;
1107
1108
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"BBBBpicture\"; filestore; sid:1; rev:1;)");
1109
    FAIL_IF_NULL(s);
1110
1111
    SigGroupBuild(de_ctx);
1112
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1113
1114
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1115
    FAIL_IF_NULL(f);
1116
    f->protoctx = &ssn;
1117
    f->proto = IPPROTO_TCP;
1118
    f->alproto = ALPROTO_HTTP1;
1119
1120
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1121
    FAIL_IF_NULL(p);
1122
    p->flow = f;
1123
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1124
    p->flowflags |= FLOW_PKT_TOSERVER;
1125
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1126
1127
    StreamTcpInitConfig(true);
1128
1129
    /* HTTP request with 1st part of the multipart body */
1130
1131
    int r = AppLayerParserParse(
1132
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1133
    FAIL_IF(r != 0);
1134
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1135
    FAIL_IF(PacketAlertCheck(p, 1));
1136
1137
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1138
    FAIL_IF(r != 0);
1139
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1140
    FAIL_IF(PacketAlertCheck(p, 1));
1141
1142
    HtpState *http_state = f->alstate;
1143
    FAIL_IF_NULL(http_state);
1144
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1145
    FAIL_IF_NULL(tx);
1146
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1147
    FAIL_IF_NULL(tx_ud);
1148
1149
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
1150
    FileContainer *fc = files.fc;
1151
    FAIL_IF_NULL(fc);
1152
    File *file = fc->head;
1153
    FAIL_IF_NULL(file);
1154
    FAIL_IF(file->flags & FILE_STORE);
1155
1156
    /* 2nd multipart body file */
1157
1158
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1159
    FAIL_IF(r != 0);
1160
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1161
    FAIL_IF(PacketAlertCheck(p, 1));
1162
1163
    r = AppLayerParserParse(
1164
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1165
    FAIL_IF(r != 0);
1166
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1167
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1168
1169
    http_state = f->alstate;
1170
    FAIL_IF_NULL(http_state);
1171
    tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1172
    FAIL_IF_NULL(tx);
1173
    tx_ud = htp_tx_get_user_data(tx);
1174
    FAIL_IF_NULL(tx_ud);
1175
1176
    files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
1177
    fc = files.fc;
1178
    FAIL_IF_NULL(fc);
1179
    file = fc->head;
1180
    FAIL_IF_NULL(file);
1181
    file = file->next;
1182
    FAIL_IF_NULL(file);
1183
    FAIL_IF_NOT(file->flags & FILE_STORE);
1184
1185
    AppLayerParserThreadCtxFree(alp_tctx);
1186
    UTHFreeFlow(f);
1187
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1188
    DetectEngineCtxFree(de_ctx);
1189
    StreamTcpFreeConfig(true);
1190
    PASS;
1191
}
1192
1193
/**
1194
 * \test multiple files in a tx. Both files should match
1195
 */
1196
static int DeStateSigTest09(void)
1197
{
1198
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1199
                         "Host: www.server.lan\r\n"
1200
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1201
                         "Content-Length: 440\r\n"
1202
                         "\r\n"
1203
                         "-----------------------------277531038314945\r\n"
1204
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1205
                         "Content-Type: image/jpeg\r\n"
1206
                         "\r\n";
1207
1208
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1209
    uint8_t httpbuf2[] = "file";
1210
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1211
    uint8_t httpbuf3[] = "content\r\n"
1212
                         "-----------------------------277531038314945\r\n";
1213
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1214
1215
    uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1216
                         "Content-Type: image/jpeg\r\n"
1217
                         "\r\n"
1218
                         "filecontent2\r\n"
1219
                         "-----------------------------277531038314945--";
1220
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1221
1222
    ThreadVars th_v;
1223
    TcpSession ssn;
1224
1225
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1226
    FAIL_IF_NULL(alp_tctx);
1227
1228
    memset(&th_v, 0, sizeof(th_v));
1229
    memset(&ssn, 0, sizeof(ssn));
1230
1231
    DetectEngineThreadCtx *det_ctx = NULL;
1232
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1233
    FAIL_IF_NULL(de_ctx);
1234
    de_ctx->flags |= DE_QUIET;
1235
1236
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filename:\"somepicture\"; filestore; sid:1; rev:1;)");
1237
    FAIL_IF_NULL(s);
1238
1239
    SigGroupBuild(de_ctx);
1240
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1241
1242
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1243
    FAIL_IF_NULL(f);
1244
    f->protoctx = &ssn;
1245
    f->proto = IPPROTO_TCP;
1246
    f->alproto = ALPROTO_HTTP1;
1247
1248
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1249
    FAIL_IF_NULL(p);
1250
    p->flow = f;
1251
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1252
    p->flowflags |= FLOW_PKT_TOSERVER;
1253
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1254
1255
    StreamTcpInitConfig(true);
1256
1257
    /* HTTP request with 1st part of the multipart body */
1258
1259
    int r = AppLayerParserParse(
1260
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1261
    FAIL_IF(r != 0);
1262
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1263
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1264
1265
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1266
    FAIL_IF(r != 0);
1267
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1268
    FAIL_IF(PacketAlertCheck(p, 1));
1269
1270
    HtpState *http_state = f->alstate;
1271
    FAIL_IF_NULL(http_state);
1272
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1273
    FAIL_IF_NULL(tx);
1274
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1275
    FAIL_IF_NULL(tx_ud);
1276
1277
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
1278
    FileContainer *fc = files.fc;
1279
    FAIL_IF_NULL(fc);
1280
    File *file = fc->head;
1281
    FAIL_IF_NULL(file);
1282
    FAIL_IF_NOT(file->flags & FILE_STORE);
1283
1284
    /* 2nd multipart body file */
1285
1286
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1287
    FAIL_IF(r != 0);
1288
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1289
    FAIL_IF(PacketAlertCheck(p, 1));
1290
1291
    r = AppLayerParserParse(
1292
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1293
    FAIL_IF(r != 0);
1294
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1295
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1296
1297
    http_state = f->alstate;
1298
    FAIL_IF_NULL(http_state);
1299
    tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1300
    FAIL_IF_NULL(tx);
1301
    tx_ud = htp_tx_get_user_data(tx);
1302
    FAIL_IF_NULL(tx_ud);
1303
1304
    files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
1305
    fc = files.fc;
1306
    FAIL_IF_NULL(fc);
1307
    file = fc->head;
1308
    FAIL_IF_NULL(file);
1309
    FAIL_IF_NOT(file->flags & FILE_STORE);
1310
1311
    AppLayerParserThreadCtxFree(alp_tctx);
1312
    UTHFreeFlow(f);
1313
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1314
    DetectEngineCtxFree(de_ctx);
1315
    StreamTcpFreeConfig(true);
1316
    PASS;
1317
}
1318
1319
/**
1320
 * \test multiple files in a tx. Both files should match. No other matches.
1321
 */
1322
static int DeStateSigTest10(void)
1323
{
1324
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1325
                         "Host: www.server.lan\r\n"
1326
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1327
                         "Content-Length: 440\r\n"
1328
                         "\r\n"
1329
                         "-----------------------------277531038314945\r\n"
1330
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1331
                         "Content-Type: image/jpeg\r\n"
1332
                         "\r\n";
1333
1334
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1335
    uint8_t httpbuf2[] = "file";
1336
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1337
    uint8_t httpbuf3[] = "content\r\n"
1338
                         "-----------------------------277531038314945\r\n";
1339
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1340
1341
    uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1342
                         "Content-Type: image/jpeg\r\n"
1343
                         "\r\n"
1344
                         "filecontent2\r\n"
1345
                         "-----------------------------277531038314945--";
1346
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1347
1348
    ThreadVars th_v;
1349
    TcpSession ssn;
1350
1351
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1352
    FAIL_IF_NULL(alp_tctx);
1353
1354
    memset(&th_v, 0, sizeof(th_v));
1355
    memset(&ssn, 0, sizeof(ssn));
1356
1357
    DetectEngineThreadCtx *det_ctx = NULL;
1358
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1359
    FAIL_IF_NULL(de_ctx);
1360
    de_ctx->flags |= DE_QUIET;
1361
1362
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (filename:\"somepicture\"; filestore; sid:1; rev:1;)");
1363
    FAIL_IF_NULL(s);
1364
1365
    SigGroupBuild(de_ctx);
1366
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1367
1368
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1369
    FAIL_IF_NULL(f);
1370
    f->protoctx = &ssn;
1371
    f->proto = IPPROTO_TCP;
1372
    f->alproto = ALPROTO_HTTP1;
1373
1374
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1375
    FAIL_IF_NULL(p);
1376
    p->flow = f;
1377
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1378
    p->flowflags |= FLOW_PKT_TOSERVER;
1379
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1380
1381
    StreamTcpInitConfig(true);
1382
1383
    /* HTTP request with 1st part of the multipart body */
1384
1385
    int r = AppLayerParserParse(
1386
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1387
    FAIL_IF(r != 0);
1388
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1389
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1390
1391
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1392
    FAIL_IF(r != 0);
1393
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1394
    FAIL_IF(PacketAlertCheck(p, 1));
1395
1396
    HtpState *http_state = f->alstate;
1397
    FAIL_IF_NULL(http_state);
1398
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1399
    FAIL_IF_NULL(tx);
1400
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1401
    FAIL_IF_NULL(tx_ud);
1402
1403
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
1404
    FileContainer *fc = files.fc;
1405
    FAIL_IF_NULL(fc);
1406
    File *file = fc->head;
1407
    FAIL_IF_NULL(file);
1408
    FAIL_IF_NOT(file->flags & FILE_STORE);
1409
1410
    /* 2nd multipart body file */
1411
1412
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1413
    FAIL_IF(r != 0);
1414
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1415
    FAIL_IF(PacketAlertCheck(p, 1));
1416
1417
    r = AppLayerParserParse(
1418
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1419
    FAIL_IF(r != 0);
1420
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1421
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1422
1423
    http_state = f->alstate;
1424
    FAIL_IF_NULL(http_state);
1425
    tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1426
    FAIL_IF_NULL(tx);
1427
    tx_ud = htp_tx_get_user_data(tx);
1428
    FAIL_IF_NULL(tx_ud);
1429
1430
    files = AppLayerParserGetTxFiles(p->flow, http_state, tx, STREAM_TOSERVER);
1431
    fc = files.fc;
1432
    FAIL_IF_NULL(fc);
1433
    file = fc->head;
1434
    FAIL_IF_NULL(file);
1435
    FAIL_IF_NOT(file->flags & FILE_STORE);
1436
1437
    AppLayerParserThreadCtxFree(alp_tctx);
1438
    UTHFreeFlow(f);
1439
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1440
    DetectEngineCtxFree(de_ctx);
1441
    StreamTcpFreeConfig(true);
1442
    PASS;
1443
}
1444
1445
#endif
1446
1447
void DeStateRegisterTests(void)
1448
0
{
1449
#ifdef UNITTESTS
1450
    UtRegisterTest("DeStateTest01", DeStateTest01);
1451
    UtRegisterTest("DeStateTest02", DeStateTest02);
1452
    UtRegisterTest("DeStateTest03", DeStateTest03);
1453
    UtRegisterTest("DeStateSigTest01", DeStateSigTest01);
1454
    UtRegisterTest("DeStateSigTest02", DeStateSigTest02);
1455
    UtRegisterTest("DeStateSigTest03", DeStateSigTest03);
1456
    UtRegisterTest("DeStateSigTest04", DeStateSigTest04);
1457
    UtRegisterTest("DeStateSigTest05", DeStateSigTest05);
1458
    UtRegisterTest("DeStateSigTest06", DeStateSigTest06);
1459
    UtRegisterTest("DeStateSigTest07", DeStateSigTest07);
1460
    UtRegisterTest("DeStateSigTest08", DeStateSigTest08);
1461
    UtRegisterTest("DeStateSigTest09", DeStateSigTest09);
1462
    UtRegisterTest("DeStateSigTest10", DeStateSigTest10);
1463
#endif
1464
1465
0
    return;
1466
0
}
1467
1468
/**
1469
 * @}
1470
 */