• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jasonish / suricata / 23105300094

15 Mar 2026 06:48AM UTC coverage: 75.784% (-0.7%) from 76.495%
23105300094

push

github

jasonish
github-ci: ubuntu minimal build fixups

- Don't run on the GitHub provided VM, it contains a newer Rust than
  stock Ubuntu does.

252836 of 333628 relevant lines covered (75.78%)

1978514.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.36
/src/detect-engine-state.c
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
static inline int StateIsValid(uint16_t alproto, void *alstate)
68
{
7✔
69
    if (alstate != NULL) {
7✔
70
        if (alproto == ALPROTO_HTTP1) {
7✔
71
            HtpState *htp_state = (HtpState *)alstate;
5✔
72
            if (htp_state->conn != NULL) {
5✔
73
                return 1;
5✔
74
            }
5✔
75
        } else {
5✔
76
            return 1;
2✔
77
        }
2✔
78
    }
7✔
79
    return 0;
×
80
}
7✔
81

82
static DeStateStore *DeStateStoreAlloc(void)
83
{
2,960✔
84
    DeStateStore *d = SCCalloc(1, sizeof(DeStateStore));
2,960✔
85
    if (unlikely(d == NULL))
2,960✔
86
        return NULL;
×
87

88
    return d;
2,960✔
89
}
2,960✔
90

91
#ifdef DEBUG_VALIDATION
92
static int DeStateSearchState(DetectEngineState *state, uint8_t direction, SigIntId num)
93
{
94
    DetectEngineStateDirection *dir_state = &state->dir_state[direction & STREAM_TOSERVER ? 0 : 1];
95
    DeStateStore *tx_store = dir_state->head;
96
    SigIntId store_cnt;
97
    SigIntId state_cnt = 0;
98

99
    for (; tx_store != NULL; tx_store = tx_store->next) {
100
        SCLogDebug("tx_store %p", tx_store);
101
        for (store_cnt = 0;
102
             store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < dir_state->cnt;
103
             store_cnt++, state_cnt++)
104
        {
105
            DeStateStoreItem *item = &tx_store->store[store_cnt];
106
            if (item->sid == num) {
107
                SCLogDebug("sid %u already in state: %p %p %p %u %u, direction %s",
108
                            num, state, dir_state, tx_store, state_cnt,
109
                            store_cnt, direction & STREAM_TOSERVER ? "toserver" : "toclient");
110
                return 1;
111
            }
112
        }
113
    }
114
    return 0;
115
}
116
#endif
117

118
static void DeStateSignatureAppend(DetectEngineState *state,
119
        const Signature *s, uint32_t inspect_flags, uint8_t direction)
120
{
3,920✔
121
    SCEnter();
3,920✔
122

123
    DetectEngineStateDirection *dir_state =
3,920✔
124
            &state->dir_state[(direction & STREAM_TOSERVER) ? 0 : 1];
3,920✔
125

126
#ifdef DEBUG_VALIDATION
127
    BUG_ON(DeStateSearchState(state, direction, s->iid));
128
#endif
129
    DeStateStore *store = dir_state->tail;
3,920✔
130
    if (store == NULL) {
3,920✔
131
        store = DeStateStoreAlloc();
2,958✔
132
        dir_state->head = store;
2,958✔
133
        dir_state->cur = store;
2,958✔
134
        dir_state->tail = store;
2,958✔
135
    } else if (dir_state->cur) {
2,958✔
136
        store = dir_state->cur;
961✔
137
    } else {
961✔
138
        store = DeStateStoreAlloc();
1✔
139
        if (store != NULL) {
1✔
140
            dir_state->tail->next = store;
1✔
141
            dir_state->tail = store;
1✔
142
            dir_state->cur = store;
1✔
143
        }
1✔
144
    }
1✔
145
    if (store == NULL)
3,920✔
146
        SCReturn;
×
147

148
    SigIntId idx = dir_state->cnt % DE_STATE_CHUNK_SIZE;
3,920✔
149
    store->store[idx].sid = s->iid;
3,920✔
150
    store->store[idx].flags = inspect_flags;
3,920✔
151
    dir_state->cnt++;
3,920✔
152
    /* if current chunk is full, progress cur */
153
    if (dir_state->cnt % DE_STATE_CHUNK_SIZE == 0) {
3,920✔
154
        dir_state->cur = dir_state->cur->next;
2✔
155
    }
2✔
156

157
    SCReturn;
3,920✔
158
}
3,920✔
159

160
DetectEngineState *DetectEngineStateAlloc(void)
161
{
2,421✔
162
    DetectEngineState *d = SCCalloc(1, sizeof(DetectEngineState));
2,421✔
163
    if (unlikely(d == NULL))
2,421✔
164
        return NULL;
×
165

166
    return d;
2,421✔
167
}
2,421✔
168

169
void SCDetectEngineStateFree(DetectEngineState *state)
170
{
2,422✔
171
    DeStateStore *store;
2,422✔
172
    DeStateStore *store_next;
2,422✔
173
    int i = 0;
2,422✔
174

175
    for (i = 0; i < 2; i++) {
7,266✔
176
        store = state->dir_state[i].head;
4,844✔
177
        while (store != NULL) {
7,804✔
178
            store_next = store->next;
2,960✔
179
            SCFree(store);
2,960✔
180
            store = store_next;
2,960✔
181
        }
2,960✔
182
    }
4,844✔
183
    SCFree(state);
2,422✔
184
}
2,422✔
185

186
static void StoreFileNoMatchCnt(DetectEngineState *de_state, uint16_t file_no_match, uint8_t direction)
187
{
3,873✔
188
    de_state->dir_state[(direction & STREAM_TOSERVER) ? 0 : 1].filestore_cnt += file_no_match;
3,873✔
189
}
3,873✔
190

191
static bool StoreFilestoreSigsCantMatch(const SigGroupHead *sgh, const DetectEngineState *de_state, uint8_t direction)
192
{
3,872✔
193
    if (de_state->dir_state[(direction & STREAM_TOSERVER) ? 0 : 1].filestore_cnt ==
3,872✔
194
            sgh->filestore_cnt)
3,872✔
195
        return true;
3,774✔
196
    else
98✔
197
        return false;
98✔
198
}
3,872✔
199

200
static void StoreStateTxHandleFiles(const SigGroupHead *sgh, Flow *f, DetectEngineState *destate,
201
        const uint8_t flow_flags, void *tx, const uint64_t tx_id, const uint16_t file_no_match)
202
{
3,873✔
203
    SCLogDebug("tx %"PRIu64", file_no_match %u", tx_id, file_no_match);
3,873✔
204
    StoreFileNoMatchCnt(destate, file_no_match, flow_flags);
3,873✔
205
    if (StoreFilestoreSigsCantMatch(sgh, destate, flow_flags)) {
3,873✔
206
        SCLogDebug("filestore sigs can't match");
3,774✔
207
        FileDisableStoringForTransaction(
3,774✔
208
                f, flow_flags & (STREAM_TOCLIENT | STREAM_TOSERVER), tx, tx_id);
3,774✔
209
    } else {
3,774✔
210
        SCLogDebug("filestore sigs can still match");
99✔
211
    }
99✔
212
}
3,873✔
213

214
void DetectRunStoreStateTx(
215
        const SigGroupHead *sgh,
216
        Flow *f, void *tx, uint64_t tx_id,
217
        const Signature *s,
218
        uint32_t inspect_flags, uint8_t flow_flags,
219
        const uint16_t file_no_match)
220
{
3,870✔
221
    AppLayerTxData *tx_data = AppLayerParserGetTxData(f->proto, f->alproto, tx);
3,870✔
222
    if (tx_data->de_state == NULL) {
3,870✔
223
        tx_data->de_state = DetectEngineStateAlloc();
2,419✔
224
        if (tx_data->de_state == NULL)
2,419✔
225
            return;
×
226
        SCLogDebug("destate created for %"PRIu64, tx_id);
2,419✔
227
    }
2,419✔
228
    DeStateSignatureAppend(tx_data->de_state, s, inspect_flags, flow_flags);
3,870✔
229
    if (s->flags & SIG_FLAG_TXBOTHDIR) {
3,870✔
230
        // add also in the other DetectEngineStateDirection
231
        DeStateSignatureAppend(tx_data->de_state, s, inspect_flags,
12✔
232
                flow_flags ^ (STREAM_TOSERVER | STREAM_TOCLIENT));
12✔
233
    }
12✔
234
    StoreStateTxHandleFiles(sgh, f, tx_data->de_state, flow_flags, tx, tx_id, file_no_match);
3,870✔
235

236
    SCLogDebug("Stored for TX %"PRIu64, tx_id);
3,870✔
237
}
3,870✔
238

239
static inline void ResetTxState(DetectEngineState *s)
240
{
7✔
241
    if (s) {
7✔
242
        s->dir_state[0].cnt = 0;
1✔
243
        s->dir_state[0].filestore_cnt = 0;
1✔
244
        s->dir_state[0].flags = 0;
1✔
245
        /* reset 'cur' back to the list head */
246
        s->dir_state[0].cur = s->dir_state[0].head;
1✔
247

248
        s->dir_state[1].cnt = 0;
1✔
249
        s->dir_state[1].filestore_cnt = 0;
1✔
250
        s->dir_state[1].flags = 0;
1✔
251
        /* reset 'cur' back to the list head */
252
        s->dir_state[1].cur = s->dir_state[1].head;
1✔
253
    }
1✔
254
}
7✔
255

256
/** \brief Reset de state for active tx'
257
 *  To be used on detect engine reload.
258
 *  \param f write LOCKED flow
259
 */
260
void DetectEngineStateResetTxs(Flow *f)
261
{
7✔
262
    void *alstate = FlowGetAppState(f);
7✔
263
    if (!StateIsValid(f->alproto, alstate)) {
7✔
264
        return;
×
265
    }
×
266

267
    uint64_t inspect_ts = AppLayerParserGetTransactionInspectId(f->alparser, STREAM_TOCLIENT);
7✔
268
    uint64_t inspect_tc = AppLayerParserGetTransactionInspectId(f->alparser, STREAM_TOSERVER);
7✔
269

270
    uint64_t inspect_tx_id = MIN(inspect_ts, inspect_tc);
7✔
271

272
    uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
7✔
273

274
    for ( ; inspect_tx_id < total_txs; inspect_tx_id++) {
13✔
275
        void *inspect_tx = AppLayerParserGetTx(f->proto, f->alproto, alstate, inspect_tx_id);
6✔
276
        if (inspect_tx != NULL) {
6✔
277
            AppLayerTxData *txd = AppLayerParserGetTxData(f->proto, f->alproto, inspect_tx);
6✔
278
            ResetTxState(txd->de_state);
6✔
279
        }
6✔
280
    }
6✔
281
}
7✔
282

283
/*********Unittests*********/
284

285
#ifdef UNITTESTS
286
#include "detect-engine-alert.h"
287

288
static int DeStateTest01(void)
289
{
1✔
290
    SCLogDebug("sizeof(DetectEngineState)\t\t%"PRIuMAX,
1✔
291
            (uintmax_t)sizeof(DetectEngineState));
1✔
292
    SCLogDebug("sizeof(DeStateStore)\t\t\t%"PRIuMAX,
1✔
293
            (uintmax_t)sizeof(DeStateStore));
1✔
294
    SCLogDebug("sizeof(DeStateStoreItem)\t\t%"PRIuMAX"",
1✔
295
            (uintmax_t)sizeof(DeStateStoreItem));
1✔
296

297
    return 1;
1✔
298
}
1✔
299

300
static int DeStateTest02(void)
301
{
1✔
302
    uint8_t direction = STREAM_TOSERVER;
1✔
303
    DetectEngineState *state = DetectEngineStateAlloc();
1✔
304
    FAIL_IF_NULL(state);
1✔
305
    FAIL_IF_NOT_NULL(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head);
1✔
306

307
    Signature s;
1✔
308
    memset(&s, 0x00, sizeof(s));
1✔
309

310
    s.iid = 0;
1✔
311
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
312
    s.iid = 11;
1✔
313
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
314
    s.iid = 22;
1✔
315
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
316
    s.iid = 33;
1✔
317
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
318
    s.iid = 44;
1✔
319
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
320
    s.iid = 55;
1✔
321
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
322
    s.iid = 66;
1✔
323
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
324
    s.iid = 77;
1✔
325
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
326
    s.iid = 88;
1✔
327
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
328
    s.iid = 99;
1✔
329
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
330
    s.iid = 100;
1✔
331
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
332
    s.iid = 111;
1✔
333
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
334
    s.iid = 122;
1✔
335
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
336
    s.iid = 133;
1✔
337
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
338
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
1✔
339
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
1✔
340

341
    s.iid = 144;
1✔
342
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
343

344
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
1✔
345
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
1✔
346
            state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
1✔
347
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur == NULL);
1✔
348

349
    s.iid = 155;
1✔
350
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
351

352
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].tail ==
1✔
353
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
1✔
354

355
    s.iid = 166;
1✔
356
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
357

358
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
1✔
359
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11);
1✔
360
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL);
1✔
361
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
1✔
362
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155);
1✔
363
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166);
1✔
364

365
    ResetTxState(state);
1✔
366

367
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
1✔
368
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
1✔
369
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
1✔
370

371
    s.iid = 0;
1✔
372
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
373
    s.iid = 11;
1✔
374
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
375
    s.iid = 22;
1✔
376
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
377
    s.iid = 33;
1✔
378
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
379
    s.iid = 44;
1✔
380
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
381
    s.iid = 55;
1✔
382
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
383
    s.iid = 66;
1✔
384
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
385
    s.iid = 77;
1✔
386
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
387
    s.iid = 88;
1✔
388
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
389
    s.iid = 99;
1✔
390
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
391
    s.iid = 100;
1✔
392
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
393
    s.iid = 111;
1✔
394
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
395
    s.iid = 122;
1✔
396
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
397
    s.iid = 133;
1✔
398
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
399
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
1✔
400
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
1✔
401
    s.iid = 144;
1✔
402
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
403
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
1✔
404
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head ==
1✔
405
            state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
1✔
406
    FAIL_IF_NOT(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].tail ==
1✔
407
                state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].cur);
1✔
408
    s.iid = 155;
1✔
409
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
410
    s.iid = 166;
1✔
411
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
412

413
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
1✔
414
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 11);
1✔
415
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next == NULL);
1✔
416
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[14].sid != 144);
1✔
417
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[0].sid != 155);
1✔
418
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->next->store[1].sid != 166);
1✔
419

420
    SCDetectEngineStateFree(state);
1✔
421

422
    PASS;
1✔
423
}
1✔
424

425
static int DeStateTest03(void)
426
{
1✔
427
    DetectEngineState *state = DetectEngineStateAlloc();
1✔
428
    FAIL_IF_NULL(state);
1✔
429

430
    Signature s;
1✔
431
    memset(&s, 0x00, sizeof(s));
1✔
432

433
    uint8_t direction = STREAM_TOSERVER;
1✔
434

435
    s.iid = 11;
1✔
436
    DeStateSignatureAppend(state, &s, 0, direction);
1✔
437
    s.iid = 22;
1✔
438
    DeStateSignatureAppend(state, &s, BIT_U32(DE_STATE_FLAG_BASE), direction);
1✔
439

440
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
1✔
441
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].sid != 11);
1✔
442
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].flags & BIT_U32(DE_STATE_FLAG_BASE));
1✔
443
    FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 22);
1✔
444
    FAIL_IF(!(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].flags & BIT_U32(DE_STATE_FLAG_BASE)));
1✔
445

446
    SCDetectEngineStateFree(state);
1✔
447
    PASS;
1✔
448
}
1✔
449

450
static int DeStateSigTest01(void)
451
{
1✔
452
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
453
    ThreadVars th_v;
1✔
454
    Flow f;
1✔
455
    TcpSession ssn;
1✔
456
    Packet *p = NULL;
1✔
457
    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\n";
1✔
458
    uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\n";
1✔
459
    uint8_t httpbuf3[] = "Cookie: dummy\r\nContent-Length: 10\r\n\r\n";
1✔
460
    uint8_t httpbuf4[] = "Http Body!";
1✔
461
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
462
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1✔
463
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1✔
464
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1✔
465

466
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
467
    FAIL_IF_NULL(alp_tctx);
1✔
468

469
    memset(&th_v, 0, sizeof(th_v));
1✔
470
    StatsThreadInit(&th_v.stats);
1✔
471
    memset(&f, 0, sizeof(f));
1✔
472
    memset(&ssn, 0, sizeof(ssn));
1✔
473

474
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
475
    FAIL_IF_NULL(p);
1✔
476

477
    FLOW_INITIALIZE(&f);
1✔
478
    f.protoctx = (void *)&ssn;
1✔
479
    f.proto = IPPROTO_TCP;
1✔
480
    f.flags |= FLOW_IPV4;
1✔
481
    f.alproto = ALPROTO_HTTP1;
1✔
482

483
    p->flow = &f;
1✔
484
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
485
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
486
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
487

488
    StreamTcpInitConfig(true);
1✔
489

490
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
491
    FAIL_IF_NULL(de_ctx);
1✔
492
    de_ctx->flags |= DE_QUIET;
1✔
493

494
    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;)");
1✔
495
    FAIL_IF_NULL(s);
1✔
496

497
    SigGroupBuild(de_ctx);
1✔
498
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
499
    FAIL_IF_NULL(det_ctx);
1✔
500

501
    int r = AppLayerParserParse(
1✔
502
            NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1✔
503
    FAIL_IF_NOT(r == 0);
1✔
504
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
505
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
506

507
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1✔
508
    FAIL_IF_NOT(r == 0);
1✔
509
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
510
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
511

512
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1✔
513
    FAIL_IF_NOT(r == 0);
1✔
514
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
515
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1✔
516

517
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
1✔
518
    FAIL_IF_NOT(r == 0);
1✔
519
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
520
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
521

522
    UTHFreePacket(p);
1✔
523
    FLOW_DESTROY(&f);
1✔
524
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
525
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
526
    DetectEngineCtxFree(de_ctx);
1✔
527
    StreamTcpFreeConfig(true);
1✔
528
    StatsThreadCleanup(&th_v.stats);
1✔
529
    PASS;
1✔
530
}
1✔
531

532
/** \test multiple pipelined http transactions */
533
static int DeStateSigTest02(void)
534
{
1✔
535
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
536
    ThreadVars th_v;
1✔
537
    Flow f;
1✔
538
    TcpSession ssn;
1✔
539
    Packet *p = NULL;
1✔
540
    uint8_t httpbuf1[] = "POST / HTTP/1.1\r\n";
1✔
541
    uint8_t httpbuf2[] = "User-Agent: Mozilla/1.0\r\nContent-Length: 10\r\n";
1✔
542
    uint8_t httpbuf3[] = "Cookie: dummy\r\n\r\n";
1✔
543
    uint8_t httpbuf4[] = "Http Body!";
1✔
544
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
545
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1✔
546
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1✔
547
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1✔
548
    uint8_t httpbuf5[] = "GET /?var=val HTTP/1.1\r\n";
1✔
549
    uint8_t httpbuf6[] = "User-Agent: Firefox/1.0\r\n";
1✔
550
    uint8_t httpbuf7[] = "Cookie: dummy2\r\nContent-Length: 10\r\n\r\nHttp Body!";
1✔
551
    uint32_t httplen5 = sizeof(httpbuf5) - 1; /* minus the \0 */
1✔
552
    uint32_t httplen6 = sizeof(httpbuf6) - 1; /* minus the \0 */
1✔
553
    uint32_t httplen7 = sizeof(httpbuf7) - 1; /* minus the \0 */
1✔
554
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
555
    FAIL_IF_NULL(alp_tctx);
1✔
556

557
    memset(&th_v, 0, sizeof(th_v));
1✔
558
    StatsThreadInit(&th_v.stats);
1✔
559
    memset(&f, 0, sizeof(f));
1✔
560
    memset(&ssn, 0, sizeof(ssn));
1✔
561

562
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
563

564
    FLOW_INITIALIZE(&f);
1✔
565
    f.protoctx = (void *)&ssn;
1✔
566
    f.proto = IPPROTO_TCP;
1✔
567
    f.flags |= FLOW_IPV4;
1✔
568

569
    p->flow = &f;
1✔
570
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
571
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
572
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
573
    f.alproto = ALPROTO_HTTP1;
1✔
574

575
    StreamTcpInitConfig(true);
1✔
576

577
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
578
    FAIL_IF_NULL(de_ctx);
1✔
579

580
    de_ctx->flags |= DE_QUIET;
1✔
581

582
    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;)");
1✔
583
    FAIL_IF_NULL(s);
1✔
584
    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;)");
1✔
585
    FAIL_IF_NULL(s);
1✔
586

587
    SigGroupBuild(de_ctx);
1✔
588
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
589
    FAIL_IF_NULL(det_ctx);
1✔
590

591
    int r = AppLayerParserParse(
1✔
592
            NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf1, httplen1);
1✔
593
    FAIL_IF(r != 0);
1✔
594
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
595
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
596

597
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1✔
598
    FAIL_IF(r != 0);
1✔
599
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
600
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
601

602
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1✔
603
    FAIL_IF(r != 0);
1✔
604
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
605
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
606

607
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f.alstate, 0);
1✔
608
    FAIL_IF_NULL(tx);
1✔
609

610
    AppLayerTxData *tx_data = AppLayerParserGetTxData(IPPROTO_TCP, ALPROTO_HTTP1, tx);
1✔
611
    FAIL_IF_NULL(tx_data);
1✔
612
    DetectEngineState *tx_de_state = tx_data->de_state;
1✔
613
    FAIL_IF_NULL(tx_de_state);
1✔
614
    FAIL_IF(tx_de_state->dir_state[0].cnt != 1);
1✔
615
    /* http_header(mpm): 5, uri: 3, method: 6, cookie: 7 */
616
    uint32_t expected_flags = (BIT_U32(5) | BIT_U32(3) | BIT_U32(6) | BIT_U32(4));
1✔
617
    FAIL_IF(tx_de_state->dir_state[0].head->store[0].flags != expected_flags);
1✔
618

619
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf4, httplen4);
1✔
620
    FAIL_IF(r != 0);
1✔
621
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
622
    FAIL_IF(!(PacketAlertCheck(p, 1)));
1✔
623

624
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf5, httplen5);
1✔
625
    FAIL_IF(r != 0);
1✔
626
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
627
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
628

629
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf6, httplen6);
1✔
630
    FAIL_IF(r != 0);
1✔
631
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
632
    FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
1✔
633

634
    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf7, httplen7);
1✔
635
    FAIL_IF(r != 0);
1✔
636
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
637
    FAIL_IF(!(PacketAlertCheck(p, 2)));
1✔
638

639
    UTHFreePacket(p);
1✔
640
    FLOW_DESTROY(&f);
1✔
641
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
642
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
643
    DetectEngineCtxFree(de_ctx);
1✔
644
    StreamTcpFreeConfig(true);
1✔
645
    StatsThreadCleanup(&th_v.stats);
1✔
646
    PASS;
1✔
647
}
1✔
648

649
static int DeStateSigTest03(void)
650
{
1✔
651
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
652
                         "Host: www.server.lan\r\n"
1✔
653
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
654
                         "Content-Length: 215\r\n"
1✔
655
                         "\r\n"
1✔
656
                         "-----------------------------277531038314945\r\n"
1✔
657
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1✔
658
                         "Content-Type: image/jpeg\r\n"
1✔
659
                         "\r\n"
1✔
660
                         "filecontent\r\n"
1✔
661
                         "-----------------------------277531038314945--";
1✔
662
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
663
    ThreadVars th_v;
1✔
664
    TcpSession ssn;
1✔
665
    Flow *f = NULL;
1✔
666
    Packet *p = NULL;
1✔
667
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
668
    FAIL_IF_NULL(alp_tctx);
1✔
669

670
    memset(&th_v, 0, sizeof(th_v));
1✔
671
    StatsThreadInit(&th_v.stats);
1✔
672
    memset(&ssn, 0, sizeof(ssn));
1✔
673

674
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
675
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
676
    FAIL_IF_NULL(de_ctx);
1✔
677

678
    de_ctx->flags |= DE_QUIET;
1✔
679

680
    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;)");
1✔
681
    FAIL_IF_NULL(s);
1✔
682

683
    SigGroupBuild(de_ctx);
1✔
684
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
685

686
    f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
687
    FAIL_IF_NULL(f);
1✔
688
    f->protoctx = &ssn;
1✔
689
    f->proto = IPPROTO_TCP;
1✔
690
    f->alproto = ALPROTO_HTTP1;
1✔
691

692
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
693
    FAIL_IF_NULL(p);
1✔
694

695
    p->flow = f;
1✔
696
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
697
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
698
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
699

700
    StreamTcpInitConfig(true);
1✔
701

702
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
1✔
703
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
1✔
704
    FAIL_IF(r != 0);
1✔
705

706
    HtpState *http_state = f->alstate;
1✔
707
    FAIL_IF_NULL(http_state);
1✔
708
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
709
    FAIL_IF_NULL(tx);
1✔
710
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
711
    FAIL_IF_NULL(tx_ud);
1✔
712

713
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
714
    FAIL_IF(!(PacketAlertCheck(p, 1)));
1✔
715

716
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
717
    FileContainer *fc = files.fc;
1✔
718
    FAIL_IF_NULL(fc);
1✔
719

720
    File *file = fc->head;
1✔
721
    FAIL_IF_NULL(file);
1✔
722

723
    FAIL_IF(!(file->flags & FILE_STORE));
1✔
724

725
    UTHFreePacket(p);
1✔
726
    UTHFreeFlow(f);
1✔
727

728
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
729
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
730
    DetectEngineCtxFree(de_ctx);
1✔
731
    StreamTcpFreeConfig(true);
1✔
732
    StatsThreadCleanup(&th_v.stats);
1✔
733
    PASS;
1✔
734
}
1✔
735

736
static int DeStateSigTest04(void)
737
{
1✔
738
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
739
                         "Host: www.server.lan\r\n"
1✔
740
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
741
                         "Content-Length: 215\r\n"
1✔
742
                         "\r\n"
1✔
743
                         "-----------------------------277531038314945\r\n"
1✔
744
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1✔
745
                         "Content-Type: image/jpeg\r\n"
1✔
746
                         "\r\n"
1✔
747
                         "filecontent\r\n"
1✔
748
                         "-----------------------------277531038314945--";
1✔
749
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
750
    ThreadVars th_v;
1✔
751
    TcpSession ssn;
1✔
752
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
753
    FAIL_IF_NULL(alp_tctx);
1✔
754

755
    memset(&th_v, 0, sizeof(th_v));
1✔
756
    StatsThreadInit(&th_v.stats);
1✔
757
    memset(&ssn, 0, sizeof(ssn));
1✔
758

759
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
760
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
761
    FAIL_IF_NULL(de_ctx);
1✔
762
    de_ctx->flags |= DE_QUIET;
1✔
763

764
    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;)");
1✔
765
    FAIL_IF_NULL(s);
1✔
766

767
    SigGroupBuild(de_ctx);
1✔
768
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
769
    FAIL_IF_NULL(det_ctx);
1✔
770

771
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
772
    FAIL_IF_NULL(f);
1✔
773
    f->protoctx = &ssn;
1✔
774
    f->proto = IPPROTO_TCP;
1✔
775
    f->alproto = ALPROTO_HTTP1;
1✔
776

777
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
778
    FAIL_IF_NULL(p);
1✔
779
    p->flow = f;
1✔
780
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
781
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
782
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
783

784
    StreamTcpInitConfig(true);
1✔
785

786
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
1✔
787
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
1✔
788
    FAIL_IF(r != 0);
1✔
789
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
790
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
791

792
    HtpState *http_state = f->alstate;
1✔
793
    FAIL_IF_NULL(http_state);
1✔
794
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
795
    FAIL_IF_NULL(tx);
1✔
796
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
797
    FAIL_IF_NULL(tx_ud);
1✔
798

799
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
800
    FileContainer *fc = files.fc;
1✔
801
    FAIL_IF_NULL(fc);
1✔
802
    File *file = fc->head;
1✔
803
    FAIL_IF_NULL(file);
1✔
804

805
    FAIL_IF(file->flags & FILE_STORE);
1✔
806

807
    UTHFreePacket(p);
1✔
808
    UTHFreeFlow(f);
1✔
809
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
810
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
811
    DetectEngineCtxFree(de_ctx);
1✔
812
    StreamTcpFreeConfig(true);
1✔
813
    StatsThreadCleanup(&th_v.stats);
1✔
814
    PASS;
1✔
815
}
1✔
816

817
static int DeStateSigTest05(void)
818
{
1✔
819
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
820
                         "Host: www.server.lan\r\n"
1✔
821
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
822
                         "Content-Length: 215\r\n"
1✔
823
                         "\r\n"
1✔
824
                         "-----------------------------277531038314945\r\n"
1✔
825
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1✔
826
                         "Content-Type: image/jpeg\r\n"
1✔
827
                         "\r\n"
1✔
828
                         "filecontent\r\n"
1✔
829
                         "-----------------------------277531038314945--";
1✔
830
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
831
    ThreadVars th_v;
1✔
832
    TcpSession ssn;
1✔
833

834
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
835
    FAIL_IF_NULL(alp_tctx);
1✔
836

837
    memset(&th_v, 0, sizeof(th_v));
1✔
838
    StatsThreadInit(&th_v.stats);
1✔
839
    memset(&ssn, 0, sizeof(ssn));
1✔
840

841
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
842
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
843
    FAIL_IF_NULL(de_ctx);
1✔
844
    de_ctx->flags |= DE_QUIET;
1✔
845

846
    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;)");
1✔
847
    FAIL_IF_NULL(s);
1✔
848

849
    SigGroupBuild(de_ctx);
1✔
850
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
851

852
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
853
    FAIL_IF_NULL(f);
1✔
854
    f->protoctx = &ssn;
1✔
855
    f->proto = IPPROTO_TCP;
1✔
856
    f->alproto = ALPROTO_HTTP1;
1✔
857

858
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
859
    FAIL_IF_NULL(p);
1✔
860
    p->flow = f;
1✔
861
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
862
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
863
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
864

865
    StreamTcpInitConfig(true);
1✔
866

867
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
1✔
868
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
1✔
869
    FAIL_IF_NOT(r == 0);
1✔
870
    HtpState *http_state = f->alstate;
1✔
871
    FAIL_IF_NULL(http_state);
1✔
872
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
873
    FAIL_IF_NULL(tx);
1✔
874
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
875
    FAIL_IF_NULL(tx_ud);
1✔
876

877
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
878
    FileContainer *fc = files.fc;
1✔
879
    FAIL_IF_NULL(fc);
1✔
880
    File *file = fc->head;
1✔
881
    FAIL_IF_NULL(file);
1✔
882
    FAIL_IF(http_state->state_data.file_flags & FLOWFILE_NO_STORE_TS);
1✔
883

884
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
885
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
886

887
    /* detect will have set FLOWFILE_NO_STORE_TS, but it won't have had
888
     * an opportunity to be applied to the file itself yet */
889
    FAIL_IF_NOT(http_state->state_data.file_flags & FLOWFILE_NO_STORE_TS);
1✔
890
    FAIL_IF(file->flags & FILE_NOSTORE);
1✔
891

892
    UTHFreePacket(p);
1✔
893
    UTHFreeFlow(f);
1✔
894
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
895
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
896
    DetectEngineCtxFree(de_ctx);
1✔
897
    StreamTcpFreeConfig(true);
1✔
898
    StatsThreadCleanup(&th_v.stats);
1✔
899
    PASS;
1✔
900
}
1✔
901

902
static int DeStateSigTest06(void)
903
{
1✔
904
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
905
                         "Host: www.server.lan\r\n"
1✔
906
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
907
                         "Content-Length: 215\r\n"
1✔
908
                         "\r\n"
1✔
909
                         "-----------------------------277531038314945\r\n"
1✔
910
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1✔
911
                         "Content-Type: image/jpeg\r\n"
1✔
912
                         "\r\n"
1✔
913
                         "filecontent\r\n"
1✔
914
                         "-----------------------------277531038314945--";
1✔
915
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
916
    ThreadVars th_v;
1✔
917
    TcpSession ssn;
1✔
918

919
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
920
    FAIL_IF_NULL(alp_tctx);
1✔
921

922
    memset(&th_v, 0, sizeof(th_v));
1✔
923
    StatsThreadInit(&th_v.stats);
1✔
924
    memset(&ssn, 0, sizeof(ssn));
1✔
925

926
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
927
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
928
    FAIL_IF_NULL(de_ctx);
1✔
929
    de_ctx->flags |= DE_QUIET;
1✔
930

931
    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;)");
1✔
932
    FAIL_IF_NULL(s);
1✔
933

934
    SigGroupBuild(de_ctx);
1✔
935
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
936
    FAIL_IF_NULL(det_ctx);
1✔
937

938
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
939
    FAIL_IF_NULL(f);
1✔
940
    f->protoctx = &ssn;
1✔
941
    f->proto = IPPROTO_TCP;
1✔
942
    f->alproto = ALPROTO_HTTP1;
1✔
943

944
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
945
    FAIL_IF_NULL(p);
1✔
946
    p->flow = f;
1✔
947
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
948
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
949
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
950

951
    StreamTcpInitConfig(true);
1✔
952

953
    int r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1,
1✔
954
            STREAM_TOSERVER | STREAM_START | STREAM_EOF, httpbuf1, httplen1);
1✔
955
    FAIL_IF(r != 0);
1✔
956
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
957
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
958

959
    HtpState *http_state = f->alstate;
1✔
960
    FAIL_IF_NULL(http_state);
1✔
961
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
962
    FAIL_IF_NULL(tx);
1✔
963
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
964
    FAIL_IF_NULL(tx_ud);
1✔
965

966
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
967
    FileContainer *fc = files.fc;
1✔
968
    FAIL_IF_NULL(fc);
1✔
969
    File *file = fc->head;
1✔
970
    FAIL_IF_NULL(file);
1✔
971
    /* detect will have set FLOWFILE_NO_STORE_TS, but it won't have had
972
     * an opportunity to be applied to the file itself yet */
973
    FAIL_IF_NOT(tx_ud->tx_data.file_flags & FLOWFILE_NO_STORE_TS);
1✔
974
    FAIL_IF(file->flags & FILE_NOSTORE);
1✔
975

976
    UTHFreePacket(p);
1✔
977
    UTHFreeFlow(f);
1✔
978
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
979
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
980
    DetectEngineCtxFree(de_ctx);
1✔
981
    StreamTcpFreeConfig(true);
1✔
982
    StatsThreadCleanup(&th_v.stats);
1✔
983
    PASS;
1✔
984
}
1✔
985

986
static int DeStateSigTest07(void)
987
{
1✔
988
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
989
                         "Host: www.server.lan\r\n"
1✔
990
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
991
                         "Content-Length: 215\r\n"
1✔
992
                         "\r\n"
1✔
993
                         "-----------------------------277531038314945\r\n"
1✔
994
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1✔
995
                         "Content-Type: image/jpeg\r\n"
1✔
996
                         "\r\n";
1✔
997

998
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
999
    uint8_t httpbuf2[] = "filecontent\r\n"
1✔
1000
                         "-----------------------------277531038314945--";
1✔
1001
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1✔
1002
    ThreadVars th_v;
1✔
1003
    TcpSession ssn;
1✔
1004

1005
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
1006
    FAIL_IF_NULL(alp_tctx);
1✔
1007

1008
    memset(&th_v, 0, sizeof(th_v));
1✔
1009
    StatsThreadInit(&th_v.stats);
1✔
1010
    memset(&ssn, 0, sizeof(ssn));
1✔
1011

1012
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
1013
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1014
    FAIL_IF_NULL(de_ctx);
1✔
1015
    de_ctx->flags |= DE_QUIET;
1✔
1016

1017
    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;)");
1✔
1018
    FAIL_IF_NULL(s);
1✔
1019

1020
    SigGroupBuild(de_ctx);
1✔
1021
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1022

1023
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
1024
    FAIL_IF_NULL(f);
1✔
1025
    f->protoctx = &ssn;
1✔
1026
    f->proto = IPPROTO_TCP;
1✔
1027
    f->alproto = ALPROTO_HTTP1;
1✔
1028

1029
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
1030
    FAIL_IF_NULL(p);
1✔
1031
    p->flow = f;
1✔
1032
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
1033
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
1034
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
1035

1036
    StreamTcpInitConfig(true);
1✔
1037

1038
    int r = AppLayerParserParse(
1✔
1039
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1✔
1040
    FAIL_IF(r != 0);
1✔
1041
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1042
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1043

1044
    r = AppLayerParserParse(
1✔
1045
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf2, httplen2);
1✔
1046
    FAIL_IF(r != 0);
1✔
1047
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1048
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1049

1050
    HtpState *http_state = f->alstate;
1✔
1051
    FAIL_IF_NULL(http_state);
1✔
1052
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
1053
    FAIL_IF_NULL(tx);
1✔
1054
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
1055
    FAIL_IF_NULL(tx_ud);
1✔
1056

1057
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
1058
    FileContainer *fc = files.fc;
1✔
1059
    FAIL_IF_NULL(fc);
1✔
1060
    File *file = fc->head;
1✔
1061
    FAIL_IF_NULL(file);
1✔
1062
    FAIL_IF(file->flags & FILE_STORE);
1✔
1063

1064
    UTHFreePacket(p);
1✔
1065
    UTHFreeFlow(f);
1✔
1066
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
1067
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1068
    DetectEngineCtxFree(de_ctx);
1✔
1069
    StreamTcpFreeConfig(true);
1✔
1070
    StatsThreadCleanup(&th_v.stats);
1✔
1071
    PASS;
1✔
1072
}
1✔
1073

1074
/**
1075
 * \test multiple files in a tx
1076
 */
1077
static int DeStateSigTest08(void)
1078
{
1✔
1079
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
1080
                         "Host: www.server.lan\r\n"
1✔
1081
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
1082
                         "Content-Length: 440\r\n"
1✔
1083
                         "\r\n"
1✔
1084
                         "-----------------------------277531038314945\r\n"
1✔
1085
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"AAAApicture1.jpg\"\r\n"
1✔
1086
                         "Content-Type: image/jpeg\r\n"
1✔
1087
                         "\r\n";
1✔
1088

1089
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
1090
    uint8_t httpbuf2[] = "file";
1✔
1091
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1✔
1092
    uint8_t httpbuf3[] = "content\r\n"
1✔
1093
                         "-----------------------------277531038314945\r\n";
1✔
1094
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1✔
1095

1096
    uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"BBBBpicture2.jpg\"\r\n"
1✔
1097
                         "Content-Type: image/jpeg\r\n"
1✔
1098
                         "\r\n"
1✔
1099
                         "filecontent2\r\n"
1✔
1100
                         "-----------------------------277531038314945--";
1✔
1101
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1✔
1102

1103
    ThreadVars th_v;
1✔
1104
    TcpSession ssn;
1✔
1105

1106
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
1107
    FAIL_IF_NULL(alp_tctx);
1✔
1108

1109
    memset(&th_v, 0, sizeof(th_v));
1✔
1110
    StatsThreadInit(&th_v.stats);
1✔
1111
    memset(&ssn, 0, sizeof(ssn));
1✔
1112

1113
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
1114
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1115
    FAIL_IF_NULL(de_ctx);
1✔
1116
    de_ctx->flags |= DE_QUIET;
1✔
1117

1118
    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;)");
1✔
1119
    FAIL_IF_NULL(s);
1✔
1120

1121
    SigGroupBuild(de_ctx);
1✔
1122
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1123

1124
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
1125
    FAIL_IF_NULL(f);
1✔
1126
    f->protoctx = &ssn;
1✔
1127
    f->proto = IPPROTO_TCP;
1✔
1128
    f->alproto = ALPROTO_HTTP1;
1✔
1129

1130
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
1131
    FAIL_IF_NULL(p);
1✔
1132
    p->flow = f;
1✔
1133
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
1134
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
1135
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
1136

1137
    StreamTcpInitConfig(true);
1✔
1138

1139
    /* HTTP request with 1st part of the multipart body */
1140

1141
    int r = AppLayerParserParse(
1✔
1142
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1✔
1143
    FAIL_IF(r != 0);
1✔
1144
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1145
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1146

1147
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1✔
1148
    FAIL_IF(r != 0);
1✔
1149
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1150
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1151

1152
    HtpState *http_state = f->alstate;
1✔
1153
    FAIL_IF_NULL(http_state);
1✔
1154
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
1155
    FAIL_IF_NULL(tx);
1✔
1156
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
1157
    FAIL_IF_NULL(tx_ud);
1✔
1158

1159
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
1160
    FileContainer *fc = files.fc;
1✔
1161
    FAIL_IF_NULL(fc);
1✔
1162
    File *file = fc->head;
1✔
1163
    FAIL_IF_NULL(file);
1✔
1164
    FAIL_IF(file->flags & FILE_STORE);
1✔
1165

1166
    /* 2nd multipart body file */
1167

1168
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1✔
1169
    FAIL_IF(r != 0);
1✔
1170
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1171
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1172

1173
    r = AppLayerParserParse(
1✔
1174
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1✔
1175
    FAIL_IF(r != 0);
1✔
1176
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1177
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1✔
1178

1179
    http_state = f->alstate;
1✔
1180
    FAIL_IF_NULL(http_state);
1✔
1181
    tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
1182
    FAIL_IF_NULL(tx);
1✔
1183
    tx_ud = htp_tx_get_user_data(tx);
1✔
1184
    FAIL_IF_NULL(tx_ud);
1✔
1185

1186
    files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
1187
    fc = files.fc;
1✔
1188
    FAIL_IF_NULL(fc);
1✔
1189
    file = fc->head;
1✔
1190
    FAIL_IF_NULL(file);
1✔
1191
    file = file->next;
1✔
1192
    FAIL_IF_NULL(file);
1✔
1193
    FAIL_IF_NOT(file->flags & FILE_STORE);
1✔
1194

1195
    UTHFreePacket(p);
1✔
1196
    UTHFreeFlow(f);
1✔
1197
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
1198
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1199
    DetectEngineCtxFree(de_ctx);
1✔
1200
    StreamTcpFreeConfig(true);
1✔
1201
    StatsThreadCleanup(&th_v.stats);
1✔
1202
    PASS;
1✔
1203
}
1✔
1204

1205
/**
1206
 * \test multiple files in a tx. Both files should match
1207
 */
1208
static int DeStateSigTest09(void)
1209
{
1✔
1210
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
1211
                         "Host: www.server.lan\r\n"
1✔
1212
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
1213
                         "Content-Length: 440\r\n"
1✔
1214
                         "\r\n"
1✔
1215
                         "-----------------------------277531038314945\r\n"
1✔
1216
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1✔
1217
                         "Content-Type: image/jpeg\r\n"
1✔
1218
                         "\r\n";
1✔
1219

1220
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
1221
    uint8_t httpbuf2[] = "file";
1✔
1222
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1✔
1223
    uint8_t httpbuf3[] = "content\r\n"
1✔
1224
                         "-----------------------------277531038314945\r\n";
1✔
1225
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1✔
1226

1227
    uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1✔
1228
                         "Content-Type: image/jpeg\r\n"
1✔
1229
                         "\r\n"
1✔
1230
                         "filecontent2\r\n"
1✔
1231
                         "-----------------------------277531038314945--";
1✔
1232
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1✔
1233

1234
    ThreadVars th_v;
1✔
1235
    TcpSession ssn;
1✔
1236

1237
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
1238
    FAIL_IF_NULL(alp_tctx);
1✔
1239

1240
    memset(&th_v, 0, sizeof(th_v));
1✔
1241
    StatsThreadInit(&th_v.stats);
1✔
1242
    memset(&ssn, 0, sizeof(ssn));
1✔
1243

1244
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
1245
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1246
    FAIL_IF_NULL(de_ctx);
1✔
1247
    de_ctx->flags |= DE_QUIET;
1✔
1248

1249
    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;)");
1✔
1250
    FAIL_IF_NULL(s);
1✔
1251

1252
    SigGroupBuild(de_ctx);
1✔
1253
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1254

1255
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
1256
    FAIL_IF_NULL(f);
1✔
1257
    f->protoctx = &ssn;
1✔
1258
    f->proto = IPPROTO_TCP;
1✔
1259
    f->alproto = ALPROTO_HTTP1;
1✔
1260

1261
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
1262
    FAIL_IF_NULL(p);
1✔
1263
    p->flow = f;
1✔
1264
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
1265
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
1266
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
1267

1268
    StreamTcpInitConfig(true);
1✔
1269

1270
    /* HTTP request with 1st part of the multipart body */
1271

1272
    int r = AppLayerParserParse(
1✔
1273
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1✔
1274
    FAIL_IF(r != 0);
1✔
1275
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1276
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1✔
1277

1278
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1✔
1279
    FAIL_IF(r != 0);
1✔
1280
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1281
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1282

1283
    HtpState *http_state = f->alstate;
1✔
1284
    FAIL_IF_NULL(http_state);
1✔
1285
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
1286
    FAIL_IF_NULL(tx);
1✔
1287
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
1288
    FAIL_IF_NULL(tx_ud);
1✔
1289

1290
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
1291
    FileContainer *fc = files.fc;
1✔
1292
    FAIL_IF_NULL(fc);
1✔
1293
    File *file = fc->head;
1✔
1294
    FAIL_IF_NULL(file);
1✔
1295
    FAIL_IF_NOT(file->flags & FILE_STORE);
1✔
1296

1297
    /* 2nd multipart body file */
1298

1299
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1✔
1300
    FAIL_IF(r != 0);
1✔
1301
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1302
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1303

1304
    r = AppLayerParserParse(
1✔
1305
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1✔
1306
    FAIL_IF(r != 0);
1✔
1307
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1308
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1✔
1309

1310
    http_state = f->alstate;
1✔
1311
    FAIL_IF_NULL(http_state);
1✔
1312
    tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
1313
    FAIL_IF_NULL(tx);
1✔
1314
    tx_ud = htp_tx_get_user_data(tx);
1✔
1315
    FAIL_IF_NULL(tx_ud);
1✔
1316

1317
    files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
1318
    fc = files.fc;
1✔
1319
    FAIL_IF_NULL(fc);
1✔
1320
    file = fc->head;
1✔
1321
    FAIL_IF_NULL(file);
1✔
1322
    FAIL_IF_NOT(file->flags & FILE_STORE);
1✔
1323

1324
    UTHFreePacket(p);
1✔
1325
    UTHFreeFlow(f);
1✔
1326
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
1327
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1328
    DetectEngineCtxFree(de_ctx);
1✔
1329
    StreamTcpFreeConfig(true);
1✔
1330
    StatsThreadCleanup(&th_v.stats);
1✔
1331
    PASS;
1✔
1332
}
1✔
1333

1334
/**
1335
 * \test multiple files in a tx. Both files should match. No other matches.
1336
 */
1337
static int DeStateSigTest10(void)
1338
{
1✔
1339
    uint8_t httpbuf1[] = "POST /upload.cgi HTTP/1.1\r\n"
1✔
1340
                         "Host: www.server.lan\r\n"
1✔
1341
                         "Content-Type: multipart/form-data; boundary=---------------------------277531038314945\r\n"
1✔
1342
                         "Content-Length: 440\r\n"
1✔
1343
                         "\r\n"
1✔
1344
                         "-----------------------------277531038314945\r\n"
1✔
1345
                         "Content-Disposition: form-data; name=\"uploadfile_0\"; filename=\"somepicture1.jpg\"\r\n"
1✔
1346
                         "Content-Type: image/jpeg\r\n"
1✔
1347
                         "\r\n";
1✔
1348

1349
    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
1✔
1350
    uint8_t httpbuf2[] = "file";
1✔
1351
    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
1✔
1352
    uint8_t httpbuf3[] = "content\r\n"
1✔
1353
                         "-----------------------------277531038314945\r\n";
1✔
1354
    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
1✔
1355

1356
    uint8_t httpbuf4[] = "Content-Disposition: form-data; name=\"uploadfile_1\"; filename=\"somepicture2.jpg\"\r\n"
1✔
1357
                         "Content-Type: image/jpeg\r\n"
1✔
1358
                         "\r\n"
1✔
1359
                         "filecontent2\r\n"
1✔
1360
                         "-----------------------------277531038314945--";
1✔
1361
    uint32_t httplen4 = sizeof(httpbuf4) - 1; /* minus the \0 */
1✔
1362

1363
    ThreadVars th_v;
1✔
1364
    TcpSession ssn;
1✔
1365

1366
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1✔
1367
    FAIL_IF_NULL(alp_tctx);
1✔
1368

1369
    memset(&th_v, 0, sizeof(th_v));
1✔
1370
    StatsThreadInit(&th_v.stats);
1✔
1371
    memset(&ssn, 0, sizeof(ssn));
1✔
1372

1373
    DetectEngineThreadCtx *det_ctx = NULL;
1✔
1374
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1375
    FAIL_IF_NULL(de_ctx);
1✔
1376
    de_ctx->flags |= DE_QUIET;
1✔
1377

1378
    Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (filename:\"somepicture\"; filestore; sid:1; rev:1;)");
1✔
1379
    FAIL_IF_NULL(s);
1✔
1380

1381
    SigGroupBuild(de_ctx);
1✔
1382
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1383

1384
    Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
1✔
1385
    FAIL_IF_NULL(f);
1✔
1386
    f->protoctx = &ssn;
1✔
1387
    f->proto = IPPROTO_TCP;
1✔
1388
    f->alproto = ALPROTO_HTTP1;
1✔
1389

1390
    Packet *p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1✔
1391
    FAIL_IF_NULL(p);
1✔
1392
    p->flow = f;
1✔
1393
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1✔
1394
    p->flowflags |= FLOW_PKT_TOSERVER;
1✔
1395
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1✔
1396

1397
    StreamTcpInitConfig(true);
1✔
1398

1399
    /* HTTP request with 1st part of the multipart body */
1400

1401
    int r = AppLayerParserParse(
1✔
1402
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_START, httpbuf1, httplen1);
1✔
1403
    FAIL_IF(r != 0);
1✔
1404
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1405
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1✔
1406

1407
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf2, httplen2);
1✔
1408
    FAIL_IF(r != 0);
1✔
1409
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1410
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1411

1412
    HtpState *http_state = f->alstate;
1✔
1413
    FAIL_IF_NULL(http_state);
1✔
1414
    void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
1415
    FAIL_IF_NULL(tx);
1✔
1416
    HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
1✔
1417
    FAIL_IF_NULL(tx_ud);
1✔
1418

1419
    AppLayerGetFileState files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
1420
    FileContainer *fc = files.fc;
1✔
1421
    FAIL_IF_NULL(fc);
1✔
1422
    File *file = fc->head;
1✔
1423
    FAIL_IF_NULL(file);
1✔
1424
    FAIL_IF_NOT(file->flags & FILE_STORE);
1✔
1425

1426
    /* 2nd multipart body file */
1427

1428
    r = AppLayerParserParse(NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER, httpbuf3, httplen3);
1✔
1429
    FAIL_IF(r != 0);
1✔
1430
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1431
    FAIL_IF(PacketAlertCheck(p, 1));
1✔
1432

1433
    r = AppLayerParserParse(
1✔
1434
            NULL, alp_tctx, f, ALPROTO_HTTP1, STREAM_TOSERVER | STREAM_EOF, httpbuf4, httplen4);
1✔
1435
    FAIL_IF(r != 0);
1✔
1436
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1437
    FAIL_IF_NOT(PacketAlertCheck(p, 1));
1✔
1438

1439
    http_state = f->alstate;
1✔
1440
    FAIL_IF_NULL(http_state);
1✔
1441
    tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, f->alstate, 0);
1✔
1442
    FAIL_IF_NULL(tx);
1✔
1443
    tx_ud = htp_tx_get_user_data(tx);
1✔
1444
    FAIL_IF_NULL(tx_ud);
1✔
1445

1446
    files = AppLayerParserGetTxFiles(p->flow, tx, STREAM_TOSERVER);
1✔
1447
    fc = files.fc;
1✔
1448
    FAIL_IF_NULL(fc);
1✔
1449
    file = fc->head;
1✔
1450
    FAIL_IF_NULL(file);
1✔
1451
    FAIL_IF_NOT(file->flags & FILE_STORE);
1✔
1452

1453
    UTHFreePacket(p);
1✔
1454
    UTHFreeFlow(f);
1✔
1455
    AppLayerParserThreadCtxFree(alp_tctx);
1✔
1456
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1457
    DetectEngineCtxFree(de_ctx);
1✔
1458
    StreamTcpFreeConfig(true);
1✔
1459
    StatsThreadCleanup(&th_v.stats);
1✔
1460
    PASS;
1✔
1461
}
1✔
1462

1463
#endif
1464

1465
void DeStateRegisterTests(void)
1466
{
1✔
1467
#ifdef UNITTESTS
1✔
1468
    UtRegisterTest("DeStateTest01", DeStateTest01);
1✔
1469
    UtRegisterTest("DeStateTest02", DeStateTest02);
1✔
1470
    UtRegisterTest("DeStateTest03", DeStateTest03);
1✔
1471
    UtRegisterTest("DeStateSigTest01", DeStateSigTest01);
1✔
1472
    UtRegisterTest("DeStateSigTest02", DeStateSigTest02);
1✔
1473
    UtRegisterTest("DeStateSigTest03", DeStateSigTest03);
1✔
1474
    UtRegisterTest("DeStateSigTest04", DeStateSigTest04);
1✔
1475
    UtRegisterTest("DeStateSigTest05", DeStateSigTest05);
1✔
1476
    UtRegisterTest("DeStateSigTest06", DeStateSigTest06);
1✔
1477
    UtRegisterTest("DeStateSigTest07", DeStateSigTest07);
1✔
1478
    UtRegisterTest("DeStateSigTest08", DeStateSigTest08);
1✔
1479
    UtRegisterTest("DeStateSigTest09", DeStateSigTest09);
1✔
1480
    UtRegisterTest("DeStateSigTest10", DeStateSigTest10);
1✔
1481
#endif
1✔
1482
}
1✔
1483

1484
/**
1485
 * @}
1486
 */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc