Coverage Report

Created: 2026-03-31 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-dce-opnum.c
Line
Count
Source
1
/* Copyright (C) 2007-2022 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22
 *
23
 * Implements dce_opnum keyword
24
 */
25
26
#include "suricata-common.h"
27
28
#include "detect.h"
29
#include "detect-parse.h"
30
31
#include "detect-engine.h"
32
#include "detect-engine-mpm.h"
33
#include "detect-engine-state.h"
34
#include "detect-engine-build.h"
35
36
#include "flow.h"
37
#include "flow-var.h"
38
#include "flow-util.h"
39
40
#include "app-layer.h"
41
#include "queue.h"
42
#include "stream-tcp-reassemble.h"
43
#include "detect-dce-opnum.h"
44
#include "detect-dce-iface.h"
45
46
#include "util-debug.h"
47
#include "util-unittest.h"
48
#include "util-unittest-helper.h"
49
#include "stream-tcp.h"
50
51
#include "rust.h"
52
53
73
#define PARSE_REGEX "^\\s*([0-9]{1,5}(\\s*-\\s*[0-9]{1,5}\\s*)?)(,\\s*[0-9]{1,5}(\\s*-\\s*[0-9]{1,5})?\\s*)*$"
54
55
static DetectParseRegex parse_regex;
56
57
static int DetectDceOpnumMatchRust(DetectEngineThreadCtx *det_ctx,
58
        Flow *f, uint8_t flags, void *state, void *txv,
59
        const Signature *s, const SigMatchCtx *m);
60
static int DetectDceOpnumSetup(DetectEngineCtx *, Signature *, const char *);
61
static void DetectDceOpnumFree(DetectEngineCtx *, void *);
62
#ifdef UNITTESTS
63
static void DetectDceOpnumRegisterTests(void);
64
#endif
65
static int g_dce_generic_list_id = 0;
66
67
/**
68
 * \brief Registers the keyword handlers for the "dce_opnum" keyword.
69
 */
70
void DetectDceOpnumRegister(void)
71
73
{
72
73
    sigmatch_table[DETECT_DCE_OPNUM].name = "dcerpc.opnum";
73
73
    sigmatch_table[DETECT_DCE_OPNUM].alias = "dce_opnum";
74
73
    sigmatch_table[DETECT_DCE_OPNUM].AppLayerTxMatch = DetectDceOpnumMatchRust;
75
73
    sigmatch_table[DETECT_DCE_OPNUM].Setup = DetectDceOpnumSetup;
76
73
    sigmatch_table[DETECT_DCE_OPNUM].Free  = DetectDceOpnumFree;
77
#ifdef UNITTESTS
78
    sigmatch_table[DETECT_DCE_OPNUM].RegisterTests = DetectDceOpnumRegisterTests;
79
#endif
80
73
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
81
82
73
    g_dce_generic_list_id = DetectBufferTypeRegister("dce_generic");
83
73
}
84
85
/**
86
 * \brief App layer match function for the "dce_opnum" keyword.
87
 *
88
 * \param t       Pointer to the ThreadVars instance.
89
 * \param det_ctx Pointer to the DetectEngineThreadCtx.
90
 * \param f       Pointer to the flow.
91
 * \param flags   Pointer to the flags indicating the flow direction.
92
 * \param state   Pointer to the app layer state data.
93
 * \param s       Pointer to the Signature instance.
94
 * \param m       Pointer to the SigMatch.
95
 *
96
 * \retval 1 On Match.
97
 * \retval 0 On no match.
98
 */
99
static int DetectDceOpnumMatchRust(DetectEngineThreadCtx *det_ctx,
100
        Flow *f, uint8_t flags, void *state, void *txv,
101
        const Signature *s, const SigMatchCtx *m)
102
8.13k
{
103
8.13k
    SCEnter();
104
105
8.13k
    if (f->alproto == ALPROTO_DCERPC) {
106
3.84k
        return rs_dcerpc_opnum_match(txv, (void *)m);
107
3.84k
    }
108
109
4.29k
    if (rs_smb_tx_match_dce_opnum(txv, (void *)m) != 1)
110
4.20k
        SCReturnInt(0);
111
112
4.29k
    SCReturnInt(1);
113
4.29k
}
114
115
/**
116
 * \brief Creates a SigMatch for the "dce_opnum" keyword being sent as argument,
117
 *        and appends it to the rs_dcerpc_opnum_matchSignature(s).
118
 *
119
 * \param de_ctx Pointer to the detection engine context.
120
 * \param s      Pointer to signature for the current Signature being parsed
121
 *               from the rules.
122
 * \param arg    Pointer to the string holding the keyword value.
123
 *
124
 * \retval 0 on success, -1 on failure
125
 */
126
127
static int DetectDceOpnumSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
128
19.2k
{
129
19.2k
    if (arg == NULL) {
130
0
        SCLogError("Error parsing dce_opnum option in "
131
0
                   "signature, option needs a value");
132
0
        return -1;
133
0
    }
134
135
19.2k
    if (DetectSignatureSetAppProto(s, ALPROTO_DCERPC) < 0)
136
129
        return -1;
137
138
19.1k
    void *dod = rs_dcerpc_opnum_parse(arg);
139
19.1k
    if (dod == NULL) {
140
9.05k
        SCLogError("Error parsing dce_opnum option in "
141
9.05k
                   "signature");
142
9.05k
        return -1;
143
9.05k
    }
144
145
10.1k
    SigMatch *sm = SigMatchAlloc();
146
10.1k
    if (sm == NULL) {
147
0
        DetectDceOpnumFree(de_ctx, dod);
148
0
        return -1;
149
0
    }
150
151
10.1k
    sm->type = DETECT_DCE_OPNUM;
152
10.1k
    sm->ctx = (void *)dod;
153
154
10.1k
    SigMatchAppendSMToList(s, sm, g_dce_generic_list_id);
155
10.1k
    return 0;
156
10.1k
}
157
158
static void DetectDceOpnumFree(DetectEngineCtx *de_ctx, void *ptr)
159
10.1k
{
160
10.1k
    SCEnter();
161
10.1k
    if (ptr != NULL) {
162
10.1k
        rs_dcerpc_opnum_free(ptr);
163
10.1k
    }
164
10.1k
    SCReturn;
165
10.1k
}
166
167
/************************************Unittests*********************************/
168
169
#ifdef UNITTESTS
170
171
/* Disabled because of bug_753.  Would be enabled, once we rewrite
172
 * dce parser */
173
#if 0
174
175
/**
176
 * \test Test a valid dce_opnum(with multiple values) with a bind, bind_ack,
177
 *       and multiple request/responses with a match test after each frag parsing.
178
 */
179
static int DetectDceOpnumTestParse10(void)
180
{
181
    int result = 0;
182
    Signature *s = NULL;
183
    ThreadVars th_v;
184
    Packet *p = NULL;
185
    Flow f;
186
    TcpSession ssn;
187
    DetectEngineThreadCtx *det_ctx = NULL;
188
    DetectEngineCtx *de_ctx = NULL;
189
    DCERPCState *dcerpc_state = NULL;
190
    int r = 0;
191
192
    uint8_t dcerpc_bind[] = {
193
        0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
194
        0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
195
        0xb8, 0x10, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x00,
196
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
197
        0x01, 0xd0, 0x8c, 0x33, 0x44, 0x22, 0xf1, 0x31,
198
        0xaa, 0xaa, 0x90, 0x00, 0x38, 0x00, 0x10, 0x03,
199
        0x01, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
200
        0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
201
        0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
202
    };
203
204
    uint8_t dcerpc_bindack[] = {
205
        0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00,
206
        0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
207
        0xb8, 0x10, 0xb8, 0x10, 0x65, 0x8e, 0x00, 0x00,
208
        0x0d, 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45, 0x5c,
209
        0x77, 0x69, 0x6e, 0x72, 0x65, 0x67, 0x00, 0x6d,
210
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211
        0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
212
        0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
213
        0x02, 0x00, 0x00, 0x00,
214
    };
215
216
    uint8_t dcerpc_request1[] = {
217
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
218
        0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
219
        0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
220
        0x2c, 0xfd, 0xb5, 0x00, 0x40, 0xaa, 0x01, 0x00,
221
        0x00, 0x00, 0x00, 0x02,
222
    };
223
224
    uint8_t dcerpc_response1[] = {
225
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
226
        0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
227
        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228
        0x00, 0x00, 0x00, 0x00, 0xf6, 0x72, 0x28, 0x9c,
229
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
230
        0x29, 0x87, 0xea, 0xe9, 0x00, 0x00, 0x00, 0x00,
231
    };
232
233
    uint8_t dcerpc_request2[] = {
234
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
235
        0xa4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
236
        0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
237
        0x00, 0x00, 0x00, 0x00, 0xf6, 0x72, 0x28, 0x9c,
238
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
239
        0x29, 0x87, 0xea, 0xe9, 0x5c, 0x00, 0x5c, 0x00,
240
        0xa8, 0xb9, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x00,
241
        0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
242
        0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00,
243
        0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00,
244
        0x5c, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00,
245
        0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00,
246
        0x66, 0x00, 0x74, 0x00, 0x5c, 0x00, 0x57, 0x00,
247
        0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00,
248
        0x77, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x43, 0x00,
249
        0x75, 0x00, 0x72, 0x00, 0x72, 0x00, 0x65, 0x00,
250
        0x6e, 0x00, 0x74, 0x00, 0x56, 0x00, 0x65, 0x00,
251
        0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00,
252
        0x6e, 0x00, 0x5c, 0x00, 0x52, 0x00, 0x75, 0x00,
253
        0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254
        0x03, 0x00, 0x00, 0x00,
255
    };
256
257
    uint8_t dcerpc_response2[] = {
258
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
259
        0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
260
        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261
        0x00, 0x00, 0x00, 0x00, 0xf7, 0x72, 0x28, 0x9c,
262
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
263
        0x29, 0x87, 0xea, 0xe9, 0x00, 0x00, 0x00, 0x00,
264
    };
265
266
    uint8_t dcerpc_request3[] = {
267
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
268
        0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
269
        0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00,
270
        0x00, 0x00, 0x00, 0x00, 0xf7, 0x72, 0x28, 0x9c,
271
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
272
        0x29, 0x87, 0xea, 0xe9, 0x0c, 0x00, 0x0c, 0x00,
273
        0x98, 0xda, 0x14, 0x00, 0x06, 0x00, 0x00, 0x00,
274
        0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
275
        0x4f, 0x00, 0x73, 0x00, 0x61, 0x00, 0x33, 0x00,
276
        0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
277
        0x18, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x54, 0x00,
278
        0x4f, 0x00, 0x53, 0x00, 0x41, 0x00, 0x33, 0x00,
279
        0x32, 0x00, 0x2e, 0x00, 0x45, 0x00, 0x58, 0x00,
280
        0x45, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
281
    };
282
283
    uint8_t dcerpc_response3[] = {
284
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
285
        0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
286
        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287
        0x00, 0x00, 0x00, 0x00,
288
    };
289
290
    uint32_t dcerpc_bind_len = sizeof(dcerpc_bind);
291
    uint32_t dcerpc_bindack_len = sizeof(dcerpc_bindack);
292
293
    uint32_t dcerpc_request1_len = sizeof(dcerpc_request1);
294
    uint32_t dcerpc_response1_len = sizeof(dcerpc_response1);
295
296
    uint32_t dcerpc_request2_len = sizeof(dcerpc_request2);
297
    uint32_t dcerpc_response2_len = sizeof(dcerpc_response2);
298
299
    uint32_t dcerpc_request3_len = sizeof(dcerpc_request3);
300
    uint32_t dcerpc_response3_len = sizeof(dcerpc_response3);
301
302
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
303
304
    memset(&th_v, 0, sizeof(th_v));
305
    memset(&f, 0, sizeof(f));
306
    memset(&ssn, 0, sizeof(ssn));
307
308
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
309
310
    FLOW_INITIALIZE(&f);
311
    f.protoctx = (void *)&ssn;
312
    f.proto = IPPROTO_TCP;
313
    p->flow = &f;
314
    p->flowflags |= FLOW_PKT_TOSERVER;
315
    p->flowflags |= FLOW_PKT_ESTABLISHED;
316
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
317
    f.alproto = ALPROTO_DCERPC;
318
319
    StreamTcpInitConfig(true);
320
321
    de_ctx = DetectEngineCtxInit();
322
    if (de_ctx == NULL) {
323
        goto end;
324
    }
325
326
    de_ctx->flags |= DE_QUIET;
327
328
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
329
            "(msg:\"DCERPC\"; dce_opnum:2,15,22; sid:1;)");
330
    if (s == NULL) {
331
        goto end;
332
    }
333
334
    SigGroupBuild(de_ctx);
335
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
336
337
    SCLogDebug("sending bind");
338
339
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER | STREAM_START,
340
                            dcerpc_bind, dcerpc_bind_len);
341
    if (r != 0) {
342
        SCLogDebug("AppLayerParse for dcerpc bind failed.  Returned %" PRId32, r);
343
        goto end;
344
    }
345
346
    dcerpc_state = f.alstate;
347
    if (dcerpc_state == NULL) {
348
        SCLogDebug("no dcerpc state: ");
349
        goto end;
350
    }
351
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
352
    p->flowflags |= FLOW_PKT_TOSERVER;
353
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
354
355
    SCLogDebug("sending bind_ack");
356
357
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT,
358
                            dcerpc_bindack, dcerpc_bindack_len);
359
    if (r != 0) {
360
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
361
        goto end;
362
    }
363
    p->flowflags &=~ FLOW_PKT_TOSERVER;
364
    p->flowflags |= FLOW_PKT_TOCLIENT;
365
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
366
367
    SCLogDebug("sending request1");
368
369
    /* request1 */
370
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER,
371
                            dcerpc_request1, dcerpc_request1_len);
372
    if (r != 0) {
373
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
374
        goto end;
375
    }
376
377
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
378
    p->flowflags |= FLOW_PKT_TOSERVER;
379
    /* do detect */
380
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
381
382
    if (!PacketAlertCheck(p, 1)) {
383
        printf("sig 1 didn't match, but should have: ");
384
        goto end;
385
    }
386
387
    SCLogDebug("sending response1");
388
389
    /* response1 */
390
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT,
391
                            dcerpc_response1, dcerpc_response1_len);
392
    if (r != 0) {
393
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
394
        goto end;
395
    }
396
397
    p->flowflags &=~ FLOW_PKT_TOSERVER;
398
    p->flowflags |= FLOW_PKT_TOCLIENT;
399
    /* do detect */
400
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
401
402
    if (PacketAlertCheck(p, 1)) {
403
        printf("sig 1 did match, shouldn't have on response1: ");
404
        goto end;
405
    }
406
407
    /* request2 */
408
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER,
409
                            dcerpc_request2, dcerpc_request2_len);
410
    if (r != 0) {
411
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
412
        goto end;
413
    }
414
415
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
416
    p->flowflags |= FLOW_PKT_TOSERVER;
417
    /* do detect */
418
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
419
420
    if (!PacketAlertCheck(p, 1)) {
421
        printf("sig 1 didn't match, but should have on request2: ");
422
        goto end;
423
    }
424
425
    /* response2 */
426
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT,
427
                            dcerpc_response2, dcerpc_response2_len);
428
    if (r != 0) {
429
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
430
        goto end;
431
    }
432
433
    p->flowflags &=~ FLOW_PKT_TOSERVER;
434
    p->flowflags |= FLOW_PKT_TOCLIENT;
435
    /* do detect */
436
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
437
438
    if (PacketAlertCheck(p, 1)) {
439
        printf("sig 1 did match, shouldn't have on response2: ");
440
        goto end;
441
    }
442
443
    /* request3 */
444
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER,
445
                            dcerpc_request3, dcerpc_request3_len);
446
    if (r != 0) {
447
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
448
        goto end;
449
    }
450
451
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
452
    p->flowflags |= FLOW_PKT_TOSERVER;
453
    /* do detect */
454
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
455
456
    if (!PacketAlertCheck(p, 1)) {
457
        printf("sig 1 didn't match, but should have on request3: ");
458
        goto end;
459
    }
460
461
    /* response3 */
462
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT | STREAM_EOF,
463
                            dcerpc_response3, dcerpc_response3_len);
464
    if (r != 0) {
465
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
466
        goto end;
467
    }
468
469
    p->flowflags &=~ FLOW_PKT_TOSERVER;
470
    p->flowflags |= FLOW_PKT_TOCLIENT;
471
    /* do detect */
472
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
473
474
    if (PacketAlertCheck(p, 1)) {
475
        printf("sig 1 did match, shouldn't have on response2: ");
476
        goto end;
477
    }
478
479
    result = 1;
480
481
 end:
482
    if (alp_tctx != NULL)
483
        AppLayerDestroyCtxThread(alp_tctx);
484
    SigGroupCleanup(de_ctx);
485
    SigCleanSignatures(de_ctx);
486
487
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
488
    DetectEngineCtxFree(de_ctx);
489
490
    StreamTcpFreeConfig(true);
491
    FLOW_DESTROY(&f);
492
493
    UTHFreePackets(&p, 1);
494
    return result;
495
}
496
497
/**
498
 * \test Test a valid dce_opnum entry(with multiple values) with multiple
499
 *       request/responses.
500
 */
501
static int DetectDceOpnumTestParse11(void)
502
{
503
    int result = 0;
504
    Signature *s = NULL;
505
    ThreadVars th_v;
506
    Packet *p = NULL;
507
    Flow f;
508
    TcpSession ssn;
509
    DetectEngineThreadCtx *det_ctx = NULL;
510
    DetectEngineCtx *de_ctx = NULL;
511
    DCERPCState *dcerpc_state = NULL;
512
    int r = 0;
513
514
    uint8_t dcerpc_request1[] = {
515
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
516
        0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
517
        0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
518
        0x2c, 0xfd, 0xb5, 0x00, 0x40, 0xaa, 0x01, 0x00,
519
        0x00, 0x00, 0x00, 0x02,
520
    };
521
522
    uint8_t dcerpc_response1[] = {
523
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
524
        0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
525
        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526
        0x00, 0x00, 0x00, 0x00, 0xf6, 0x72, 0x28, 0x9c,
527
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
528
        0x29, 0x87, 0xea, 0xe9, 0x00, 0x00, 0x00, 0x00,
529
    };
530
531
    uint8_t dcerpc_request2[] = {
532
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
533
        0xa4, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
534
        0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
535
        0x00, 0x00, 0x00, 0x00, 0xf6, 0x72, 0x28, 0x9c,
536
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
537
        0x29, 0x87, 0xea, 0xe9, 0x5c, 0x00, 0x5c, 0x00,
538
        0xa8, 0xb9, 0x14, 0x00, 0x2e, 0x00, 0x00, 0x00,
539
        0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
540
        0x53, 0x00, 0x4f, 0x00, 0x46, 0x00, 0x54, 0x00,
541
        0x57, 0x00, 0x41, 0x00, 0x52, 0x00, 0x45, 0x00,
542
        0x5c, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00,
543
        0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00,
544
        0x66, 0x00, 0x74, 0x00, 0x5c, 0x00, 0x57, 0x00,
545
        0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00,
546
        0x77, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x43, 0x00,
547
        0x75, 0x00, 0x72, 0x00, 0x72, 0x00, 0x65, 0x00,
548
        0x6e, 0x00, 0x74, 0x00, 0x56, 0x00, 0x65, 0x00,
549
        0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00,
550
        0x6e, 0x00, 0x5c, 0x00, 0x52, 0x00, 0x75, 0x00,
551
        0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552
        0x03, 0x00, 0x00, 0x00,
553
    };
554
555
    uint8_t dcerpc_response2[] = {
556
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
557
        0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
558
        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559
        0x00, 0x00, 0x00, 0x00, 0xf7, 0x72, 0x28, 0x9c,
560
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
561
        0x29, 0x87, 0xea, 0xe9, 0x00, 0x00, 0x00, 0x00,
562
    };
563
564
    uint8_t dcerpc_request3[] = {
565
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
566
        0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
567
        0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00,
568
        0x00, 0x00, 0x00, 0x00, 0xf7, 0x72, 0x28, 0x9c,
569
        0xf0, 0x57, 0xd8, 0x11, 0xb0, 0x05, 0x00, 0x0c,
570
        0x29, 0x87, 0xea, 0xe9, 0x0c, 0x00, 0x0c, 0x00,
571
        0x98, 0xda, 0x14, 0x00, 0x06, 0x00, 0x00, 0x00,
572
        0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
573
        0x4f, 0x00, 0x73, 0x00, 0x61, 0x00, 0x33, 0x00,
574
        0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
575
        0x18, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x54, 0x00,
576
        0x4f, 0x00, 0x53, 0x00, 0x41, 0x00, 0x33, 0x00,
577
        0x32, 0x00, 0x2e, 0x00, 0x45, 0x00, 0x58, 0x00,
578
        0x45, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
579
    };
580
581
    uint8_t dcerpc_response3[] = {
582
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
583
        0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
584
        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585
        0x00, 0x00, 0x00, 0x00,
586
    };
587
588
    uint32_t dcerpc_request1_len = sizeof(dcerpc_request1);
589
    uint32_t dcerpc_response1_len = sizeof(dcerpc_response1);
590
591
    uint32_t dcerpc_request2_len = sizeof(dcerpc_request2);
592
    uint32_t dcerpc_response2_len = sizeof(dcerpc_response2);
593
594
    uint32_t dcerpc_request3_len = sizeof(dcerpc_request3);
595
    uint32_t dcerpc_response3_len = sizeof(dcerpc_response3);
596
597
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
598
599
    memset(&th_v, 0, sizeof(th_v));
600
    memset(&f, 0, sizeof(f));
601
    memset(&ssn, 0, sizeof(ssn));
602
603
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
604
605
    FLOW_INITIALIZE(&f);
606
    f.protoctx = (void *)&ssn;
607
    f.proto = IPPROTO_TCP;
608
    p->flow = &f;
609
    p->flowflags |= FLOW_PKT_TOSERVER;
610
    p->flowflags |= FLOW_PKT_ESTABLISHED;
611
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
612
    f.alproto = ALPROTO_DCERPC;
613
614
    StreamTcpInitConfig(true);
615
616
    de_ctx = DetectEngineCtxInit();
617
    if (de_ctx == NULL)
618
        goto end;
619
620
    de_ctx->flags |= DE_QUIET;
621
622
    s = de_ctx->sig_list = SigInit(de_ctx,
623
                                   "alert tcp any any -> any any "
624
                                   "(msg:\"DCERPC\"; "
625
                                   "dce_opnum:2-22; "
626
                                   "sid:1;)");
627
    if (s == NULL)
628
        goto end;
629
630
    SigGroupBuild(de_ctx);
631
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
632
633
    /* request1 */
634
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER | STREAM_START,
635
                            dcerpc_request1, dcerpc_request1_len);
636
    if (r != 0) {
637
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
638
        printf("AppLayerParse for dcerpcrequest1 failed.  Returned %" PRId32, r);
639
        goto end;
640
    }
641
642
    dcerpc_state = f.alstate;
643
    if (dcerpc_state == NULL) {
644
        SCLogDebug("no dcerpc state: ");
645
        printf("no dcerpc state: ");
646
        goto end;
647
    }
648
649
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
650
    p->flowflags |= FLOW_PKT_TOSERVER;
651
    /* do detect */
652
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
653
654
    if (!PacketAlertCheck(p, 1))
655
        goto end;
656
657
    /* response1 */
658
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT,
659
                            dcerpc_response1, dcerpc_response1_len);
660
    if (r != 0) {
661
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
662
        printf("AppLayerParse for dcerpcresponse1 failed.  Returned %" PRId32, r);
663
        goto end;
664
    }
665
666
    p->flowflags &=~ FLOW_PKT_TOSERVER;
667
    p->flowflags |= FLOW_PKT_TOCLIENT;
668
    /* do detect */
669
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
670
671
    if (PacketAlertCheck(p, 1))
672
        goto end;
673
674
    /* request2 */
675
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER,
676
                            dcerpc_request2, dcerpc_request2_len);
677
    if (r != 0) {
678
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
679
        printf("AppLayerParse for dcerpcrequest2 failed.  Returned %" PRId32, r);
680
        goto end;
681
    }
682
683
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
684
    p->flowflags |= FLOW_PKT_TOSERVER;
685
    /* do detect */
686
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
687
688
    if (!PacketAlertCheck(p, 1))
689
        goto end;
690
691
    /* response2 */
692
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT,
693
                            dcerpc_response2, dcerpc_response2_len);
694
    if (r != 0) {
695
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
696
        printf("AppLayerParse for dcerpcresponse2 failed.  Returned %" PRId32, r);
697
        goto end;
698
    }
699
700
    p->flowflags &=~ FLOW_PKT_TOSERVER;
701
    p->flowflags |= FLOW_PKT_TOCLIENT;
702
    /* do detect */
703
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
704
705
    if (PacketAlertCheck(p, 1))
706
        goto end;
707
708
    /* request3 */
709
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER,
710
                            dcerpc_request3, dcerpc_request3_len);
711
    if (r != 0) {
712
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
713
        printf("AppLayerParse for dcerpc request3 failed.  Returned %" PRId32, r);
714
        goto end;
715
    }
716
717
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
718
    p->flowflags |= FLOW_PKT_TOSERVER;
719
    /* do detect */
720
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
721
722
    if (!PacketAlertCheck(p, 1))
723
        goto end;
724
725
    /* response3 */
726
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT | STREAM_EOF,
727
                            dcerpc_response3, dcerpc_response3_len);
728
    if (r != 0) {
729
        SCLogDebug("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
730
        printf("AppLayerParse for dcerpc response3 failed.  Returned %" PRId32, r);
731
        goto end;
732
    }
733
734
    p->flowflags &=~ FLOW_PKT_TOSERVER;
735
    p->flowflags |= FLOW_PKT_TOCLIENT;
736
    /* do detect */
737
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
738
739
    if (PacketAlertCheck(p, 1))
740
        goto end;
741
742
    result = 1;
743
744
 end:
745
    if (alp_tctx != NULL)
746
        AppLayerDestroyCtxThread(alp_tctx);
747
    SigGroupCleanup(de_ctx);
748
    SigCleanSignatures(de_ctx);
749
750
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
751
    DetectEngineCtxFree(de_ctx);
752
753
    StreamTcpFreeConfig(true);
754
    FLOW_DESTROY(&f);
755
756
    UTHFreePackets(&p, 1);
757
    return result;
758
}
759
760
/**
761
 * \test Test a valid dce_opnum(with multiple values) with a bind, bind_ack,
762
 *       and multiple request/responses with a match test after each frag parsing.
763
 */
764
static int DetectDceOpnumTestParse12(void)
765
{
766
    int result = 0;
767
    Signature *s = NULL;
768
    ThreadVars th_v;
769
    Packet *p = NULL;
770
    Flow f;
771
    TcpSession ssn;
772
    DetectEngineThreadCtx *det_ctx = NULL;
773
    DetectEngineCtx *de_ctx = NULL;
774
    DCERPCState *dcerpc_state = NULL;
775
    int r = 0;
776
777
    uint8_t dcerpc_bind[] = {
778
        0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
779
        0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
780
        0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00,
781
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
782
        0x40, 0xfd, 0x2c, 0x34, 0x6c, 0x3c, 0xce, 0x11,
783
        0xa8, 0x93, 0x08, 0x00, 0x2b, 0x2e, 0x9c, 0x6d,
784
        0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
785
        0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
786
        0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
787
    };
788
789
    uint8_t dcerpc_bindack[] = {
790
        0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00,
791
        0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
792
        0xb8, 0x10, 0xb8, 0x10, 0x7d, 0xd8, 0x00, 0x00,
793
        0x0d, 0x00, 0x5c, 0x70, 0x69, 0x70, 0x65, 0x5c,
794
        0x6c, 0x6c, 0x73, 0x72, 0x70, 0x63, 0x00, 0x00,
795
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
796
        0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
797
        0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
798
        0x02, 0x00, 0x00, 0x00,
799
    };
800
801
    uint8_t dcerpc_request1[] = {
802
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
803
        0x9a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
804
        0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, //opnum is 0x28 0x00
805
        0x00, 0x00, 0x00, 0x00, 0x07, 0x9f, 0x13, 0xd9,
806
        0x2d, 0x97, 0xf4, 0x4a, 0xac, 0xc2, 0xbc, 0x70,
807
        0xec, 0xaa, 0x9a, 0xd3, 0x01, 0x00, 0x00, 0x00,
808
        0x01, 0x00, 0x00, 0x00, 0x40, 0x80, 0x40, 0x00,
809
        0x44, 0x80, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00,
810
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811
        0x09, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x00, 0x4e,
812
        0x61, 0x6d, 0x65, 0x00, 0x35, 0x39, 0x31, 0x63,
813
        0x64, 0x30, 0x35, 0x38, 0x00, 0x00, 0x00, 0x00,
814
        0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815
        0x17, 0x00, 0x00, 0x00, 0xd0, 0x2e, 0x08, 0x00,
816
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
817
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
818
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
819
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
820
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
821
        0x00, 0x00
822
    };
823
824
    uint8_t dcerpc_response1[] = {
825
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
826
        0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
827
        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828
        0x00, 0x00, 0x00, 0x00,
829
    };
830
831
    uint8_t dcerpc_request2[] = {
832
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
833
        0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
834
        0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
835
        0x00, 0x00, 0x00, 0x00, 0x07, 0x9f, 0x13, 0xd9,
836
        0x2d, 0x97, 0xf4, 0x4a, 0xac, 0xc2, 0xbc, 0x70,
837
        0xec, 0xaa, 0x9a, 0xd3, 0x09, 0x00, 0x00, 0x00,
838
        0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
839
        0x4d, 0x6f, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00,
840
        0x35, 0x39, 0x31, 0x63, 0x64, 0x30, 0x35, 0x38,
841
        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
842
        0x4e, 0x6f, 0x6e, 0x65
843
    };
844
845
    uint8_t dcerpc_response2[] = {
846
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
847
        0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
848
        0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
849
        0xd8, 0x17, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
850
        0x58, 0x1d, 0x08, 0x00, 0xe8, 0x32, 0x08, 0x00,
851
        0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
852
        0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
853
        0x4d, 0x6f, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00,
854
        0x35, 0x39, 0x31, 0x63, 0x64, 0x30, 0x35, 0x38,
855
        0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
856
        0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
857
        0xd0, 0x2e, 0x08, 0x00, 0x41, 0x41, 0x41, 0x41,
858
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
859
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
860
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
861
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
862
        0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00,
863
        0x00, 0x00, 0x00, 0x00,
864
    };
865
866
    uint32_t dcerpc_bind_len = sizeof(dcerpc_bind);
867
    uint32_t dcerpc_bindack_len = sizeof(dcerpc_bindack);
868
869
    uint32_t dcerpc_request1_len = sizeof(dcerpc_request1);
870
    uint32_t dcerpc_response1_len = sizeof(dcerpc_response1);
871
872
    uint32_t dcerpc_request2_len = sizeof(dcerpc_request2);
873
    uint32_t dcerpc_response2_len = sizeof(dcerpc_response2);
874
875
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
876
877
    memset(&th_v, 0, sizeof(th_v));
878
    memset(&f, 0, sizeof(f));
879
    memset(&ssn, 0, sizeof(ssn));
880
881
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
882
883
    FLOW_INITIALIZE(&f);
884
    f.protoctx = (void *)&ssn;
885
    f.proto = IPPROTO_TCP;
886
    p->flow = &f;
887
    p->flowflags |= FLOW_PKT_TOSERVER;
888
    p->flowflags |= FLOW_PKT_ESTABLISHED;
889
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
890
    f.alproto = ALPROTO_DCERPC;
891
892
    StreamTcpInitConfig(true);
893
894
    de_ctx = DetectEngineCtxInit();
895
    if (de_ctx == NULL)
896
        goto end;
897
898
    de_ctx->flags |= DE_QUIET;
899
900
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
901
            "(msg:\"DCERPC\"; dce_opnum:30, 40; sid:1;)");
902
    if (s == NULL)
903
        goto end;
904
905
    SigGroupBuild(de_ctx);
906
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
907
908
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER | STREAM_START,
909
                            dcerpc_bind, dcerpc_bind_len);
910
    if (r != 0) {
911
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
912
        goto end;
913
    }
914
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
915
    p->flowflags |= FLOW_PKT_TOSERVER;
916
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
917
918
    dcerpc_state = f.alstate;
919
    if (dcerpc_state == NULL) {
920
        printf("no dcerpc state: ");
921
        goto end;
922
    }
923
924
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT, dcerpc_bindack,
925
                            dcerpc_bindack_len);
926
    if (r != 0) {
927
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
928
        goto end;
929
    }
930
    p->flowflags &=~ FLOW_PKT_TOSERVER;
931
    p->flowflags |= FLOW_PKT_TOCLIENT;
932
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
933
934
    /* request1 */
935
    SCLogDebug("Sending request1");
936
937
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER, dcerpc_request1,
938
                            dcerpc_request1_len);
939
    if (r != 0) {
940
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
941
        goto end;
942
    }
943
944
    dcerpc_state = f.alstate;
945
    if (dcerpc_state == NULL) {
946
        printf("no dcerpc state: ");
947
        goto end;
948
    }
949
950
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 40) {
951
        printf("dcerpc state holding invalid opnum.  Holding %d, while we are "
952
               "expecting 40: ", dcerpc_state->dcerpc.dcerpcrequest.opnum);
953
        goto end;
954
    }
955
956
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
957
    p->flowflags |= FLOW_PKT_TOSERVER;
958
    /* do detect */
959
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
960
961
    if (!PacketAlertCheck(p, 1)) {
962
        printf("signature 1 didn't match, should have: ");
963
        goto end;
964
    }
965
966
    /* response1 */
967
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT, dcerpc_response1,
968
                            dcerpc_response1_len);
969
    if (r != 0) {
970
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
971
        goto end;
972
    }
973
974
    dcerpc_state = f.alstate;
975
    if (dcerpc_state == NULL) {
976
        printf("no dcerpc state: ");
977
        goto end;
978
    }
979
980
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 40) {
981
        printf("dcerpc state holding invalid opnum.  Holding %d, while we are "
982
               "expecting 40\n", dcerpc_state->dcerpc.dcerpcrequest.opnum);
983
        goto end;
984
    }
985
986
    p->flowflags &=~ FLOW_PKT_TOSERVER;
987
    p->flowflags |= FLOW_PKT_TOCLIENT;
988
    /* do detect */
989
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
990
991
    if (PacketAlertCheck(p, 1)) {
992
        printf("sig 1 matched on response 1, but shouldn't: ");
993
        goto end;
994
    }
995
996
    /* request2 */
997
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER, dcerpc_request2,
998
                            dcerpc_request2_len);
999
    if (r != 0) {
1000
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
1001
        goto end;
1002
    }
1003
1004
    dcerpc_state = f.alstate;
1005
    if (dcerpc_state == NULL) {
1006
        printf("no dcerpc state: ");
1007
        goto end;
1008
    }
1009
1010
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 30) {
1011
        printf("dcerpc state holding invalid opnum.  Holding %d, while we are "
1012
               "expecting 30\n", dcerpc_state->dcerpc.dcerpcrequest.opnum);
1013
        goto end;
1014
    }
1015
1016
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
1017
    p->flowflags |= FLOW_PKT_TOSERVER;
1018
    /* do detect */
1019
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1020
1021
    if (!PacketAlertCheck(p, 1)) {
1022
        printf("sig 1 didn't match on request 2: ");
1023
        goto end;
1024
    }
1025
1026
    /* response2 */
1027
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT | STREAM_EOF, dcerpc_response2,
1028
                            dcerpc_response2_len);
1029
    if (r != 0) {
1030
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
1031
        goto end;
1032
    }
1033
1034
    dcerpc_state = f.alstate;
1035
    if (dcerpc_state == NULL) {
1036
        printf("no dcerpc state: ");
1037
        goto end;
1038
    }
1039
1040
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 30) {
1041
        printf("dcerpc state holding invalid opnum.  Holding %d, while we are "
1042
               "expecting 30\n", dcerpc_state->dcerpc.dcerpcrequest.opnum);
1043
        goto end;
1044
    }
1045
1046
    p->flowflags &=~ FLOW_PKT_TOSERVER;
1047
    p->flowflags |= FLOW_PKT_TOCLIENT;
1048
    /* do detect */
1049
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1050
1051
    if (PacketAlertCheck(p, 1)) {
1052
        printf("sig 1 matched on response2, but shouldn't: ");
1053
        goto end;
1054
    }
1055
1056
    result = 1;
1057
1058
end:
1059
    if (alp_tctx != NULL)
1060
        AppLayerDestroyCtxThread(alp_tctx);
1061
    SigGroupCleanup(de_ctx);
1062
    SigCleanSignatures(de_ctx);
1063
1064
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1065
    DetectEngineCtxFree(de_ctx);
1066
1067
    StreamTcpFreeConfig(true);
1068
    FLOW_DESTROY(&f);
1069
1070
    UTHFreePackets(&p, 1);
1071
    return result;
1072
}
1073
1074
/**
1075
 * \test Test a valid dce_opnum(with multiple values) with a bind, bind_ack,
1076
 *       and multiple request/responses with a match test after each frag parsing.
1077
 */
1078
static int DetectDceOpnumTestParse13(void)
1079
{
1080
    int result = 0;
1081
    Signature *s = NULL;
1082
    ThreadVars th_v;
1083
    Packet *p = NULL;
1084
    Flow f;
1085
    TcpSession ssn;
1086
    DetectEngineThreadCtx *det_ctx = NULL;
1087
    DetectEngineCtx *de_ctx = NULL;
1088
    DCERPCState *dcerpc_state = NULL;
1089
    int r = 0;
1090
1091
    uint8_t dcerpc_request1[] = {
1092
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
1093
        0x9a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1094
        0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00,
1095
        0x00, 0x00, 0x00, 0x00, 0x07, 0x9f, 0x13, 0xd9,
1096
        0x2d, 0x97, 0xf4, 0x4a, 0xac, 0xc2, 0xbc, 0x70,
1097
        0xec, 0xaa, 0x9a, 0xd3, 0x01, 0x00, 0x00, 0x00,
1098
        0x01, 0x00, 0x00, 0x00, 0x40, 0x80, 0x40, 0x00,
1099
        0x44, 0x80, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00,
1100
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1101
        0x09, 0x00, 0x00, 0x00, 0x4d, 0x6f, 0x00, 0x4e,
1102
        0x61, 0x6d, 0x65, 0x00, 0x35, 0x39, 0x31, 0x63,
1103
        0x64, 0x30, 0x35, 0x38, 0x00, 0x00, 0x00, 0x00,
1104
        0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1105
        0x17, 0x00, 0x00, 0x00, 0xd0, 0x2e, 0x08, 0x00,
1106
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1107
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1108
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1109
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1110
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1111
        0x00, 0x00
1112
    };
1113
1114
    uint8_t dcerpc_response1[] = {
1115
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
1116
        0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1117
        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1118
        0x00, 0x00, 0x00, 0x00,
1119
    };
1120
1121
    uint8_t dcerpc_request2[] = {
1122
        0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
1123
        0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1124
        0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00,
1125
        0x00, 0x00, 0x00, 0x00, 0x07, 0x9f, 0x13, 0xd9,
1126
        0x2d, 0x97, 0xf4, 0x4a, 0xac, 0xc2, 0xbc, 0x70,
1127
        0xec, 0xaa, 0x9a, 0xd3, 0x09, 0x00, 0x00, 0x00,
1128
        0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1129
        0x4d, 0x6f, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00,
1130
        0x35, 0x39, 0x31, 0x63, 0x64, 0x30, 0x35, 0x38,
1131
        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1132
        0x4e, 0x6f, 0x6e, 0x65
1133
    };
1134
1135
    uint8_t dcerpc_response2[] = {
1136
        0x05, 0x00, 0x02, 0x03, 0x10, 0x00, 0x00, 0x00,
1137
        0x8c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1138
        0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1139
        0xd8, 0x17, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
1140
        0x58, 0x1d, 0x08, 0x00, 0xe8, 0x32, 0x08, 0x00,
1141
        0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1142
        0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1143
        0x4d, 0x6f, 0x00, 0x4e, 0x61, 0x6d, 0x65, 0x00,
1144
        0x35, 0x39, 0x31, 0x63, 0x64, 0x30, 0x35, 0x38,
1145
        0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1146
        0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
1147
        0xd0, 0x2e, 0x08, 0x00, 0x41, 0x41, 0x41, 0x41,
1148
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1149
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1150
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1151
        0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
1152
        0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00,
1153
        0x00, 0x00, 0x00, 0x00,
1154
    };
1155
1156
    uint32_t dcerpc_request1_len = sizeof(dcerpc_request1);
1157
    uint32_t dcerpc_response1_len = sizeof(dcerpc_response1);
1158
1159
    uint32_t dcerpc_request2_len = sizeof(dcerpc_request2);
1160
    uint32_t dcerpc_response2_len = sizeof(dcerpc_response2);
1161
1162
    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
1163
1164
    memset(&th_v, 0, sizeof(th_v));
1165
    memset(&f, 0, sizeof(f));
1166
    memset(&ssn, 0, sizeof(ssn));
1167
1168
    p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
1169
1170
    FLOW_INITIALIZE(&f);
1171
    f.protoctx = (void *)&ssn;
1172
    f.proto = IPPROTO_TCP;
1173
    p->flow = &f;
1174
    p->flowflags |= FLOW_PKT_TOSERVER;
1175
    p->flowflags |= FLOW_PKT_ESTABLISHED;
1176
    p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
1177
    f.alproto = ALPROTO_DCERPC;
1178
1179
    StreamTcpInitConfig(true);
1180
1181
    de_ctx = DetectEngineCtxInit();
1182
    if (de_ctx == NULL)
1183
        goto end;
1184
1185
    de_ctx->flags |= DE_QUIET;
1186
1187
    s = de_ctx->sig_list = SigInit(de_ctx,
1188
                                   "alert tcp any any -> any any "
1189
                                   "(msg:\"DCERPC\"; "
1190
                                   "dce_opnum:30, 40; "
1191
                                   "sid:1;)");
1192
    if (s == NULL)
1193
        goto end;
1194
1195
    SigGroupBuild(de_ctx);
1196
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1197
1198
    /* request1 */
1199
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER, dcerpc_request1,
1200
                            dcerpc_request1_len);
1201
    if (r != 0) {
1202
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
1203
        goto end;
1204
    }
1205
1206
    dcerpc_state = f.alstate;
1207
    if (dcerpc_state == NULL) {
1208
        printf("no dcerpc state: ");
1209
        goto end;
1210
    }
1211
1212
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 40) {
1213
        printf("dcerpc state holding invalid opnum after request1.  Holding %d, while we are "
1214
               "expecting 40\n", dcerpc_state->dcerpc.dcerpcrequest.opnum);
1215
        goto end;
1216
    }
1217
1218
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
1219
    p->flowflags |= FLOW_PKT_TOSERVER;
1220
    /* do detect */
1221
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1222
1223
    if (!PacketAlertCheck(p, 1))
1224
        goto end;
1225
1226
    /* response1 */
1227
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT, dcerpc_response1,
1228
                            dcerpc_response1_len);
1229
    if (r != 0) {
1230
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
1231
        goto end;
1232
    }
1233
1234
    dcerpc_state = f.alstate;
1235
    if (dcerpc_state == NULL) {
1236
        printf("no dcerpc state: ");
1237
        goto end;
1238
    }
1239
1240
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 40) {
1241
        printf("dcerpc state holding invalid opnum after response1.  Holding %d, while we are "
1242
               "expecting 40\n", dcerpc_state->dcerpc.dcerpcrequest.opnum);
1243
        goto end;
1244
    }
1245
1246
    p->flowflags &=~ FLOW_PKT_TOSERVER;
1247
    p->flowflags |= FLOW_PKT_TOCLIENT;
1248
    /* do detect */
1249
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1250
1251
    if (PacketAlertCheck(p, 1))
1252
        goto end;
1253
1254
    /* request2 */
1255
    printf("Sending Request2\n");
1256
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOSERVER, dcerpc_request2,
1257
                            dcerpc_request2_len);
1258
    if (r != 0) {
1259
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
1260
        goto end;
1261
    }
1262
1263
    dcerpc_state = f.alstate;
1264
    if (dcerpc_state == NULL) {
1265
        printf("no dcerpc state: ");
1266
        goto end;
1267
    }
1268
1269
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 30) {
1270
        printf("dcerpc state holding invalid opnum after request2.  Holding %d, while we are "
1271
               "expecting 30\n", dcerpc_state->dcerpc.dcerpcrequest.opnum);
1272
        goto end;
1273
    }
1274
1275
    p->flowflags &=~ FLOW_PKT_TOCLIENT;
1276
    p->flowflags |= FLOW_PKT_TOSERVER;
1277
    /* do detect */
1278
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1279
1280
    if (!PacketAlertCheck(p, 1))
1281
        goto end;
1282
1283
    /* response2 */
1284
    r = AppLayerParserParse(alp_tctx, &f, ALPROTO_DCERPC, STREAM_TOCLIENT | STREAM_EOF, dcerpc_response2,
1285
                            dcerpc_response2_len);
1286
    if (r != 0) {
1287
        printf("AppLayerParse for dcerpc failed.  Returned %" PRId32, r);
1288
        goto end;
1289
    }
1290
1291
    dcerpc_state = f.alstate;
1292
    if (dcerpc_state == NULL) {
1293
        printf("no dcerpc state: ");
1294
        goto end;
1295
    }
1296
1297
    if (dcerpc_state->dcerpc.dcerpcrequest.opnum != 30) {
1298
        printf("dcerpc state holding invalid opnum after response2.  Holding %d, while we are "
1299
               "expecting 30\n", dcerpc_state->dcerpc.dcerpcrequest.opnum);
1300
        goto end;
1301
    }
1302
1303
    p->flowflags &=~ FLOW_PKT_TOSERVER;
1304
    p->flowflags |= FLOW_PKT_TOCLIENT;
1305
    /* do detect */
1306
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1307
1308
    if (PacketAlertCheck(p, 1))
1309
        goto end;
1310
1311
    result = 1;
1312
1313
 end:
1314
    if (alp_tctx != NULL)
1315
        AppLayerDestroyCtxThread(alp_tctx);
1316
    SigGroupCleanup(de_ctx);
1317
    SigCleanSignatures(de_ctx);
1318
1319
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1320
    DetectEngineCtxFree(de_ctx);
1321
1322
    StreamTcpFreeConfig(true);
1323
    FLOW_DESTROY(&f);
1324
1325
    UTHFreePackets(&p, 1);
1326
    return result;
1327
}
1328
#endif
1329
1330
static void DetectDceOpnumRegisterTests(void)
1331
{
1332
    /* Disabled because of bug_753.  Would be enabled, once we rewrite
1333
     * dce parser */
1334
#if 0
1335
    UtRegisterTest("DetectDceOpnumTestParse10", DetectDceOpnumTestParse10, 1);
1336
    UtRegisterTest("DetectDceOpnumTestParse11", DetectDceOpnumTestParse11, 1);
1337
    UtRegisterTest("DetectDceOpnumTestParse12", DetectDceOpnumTestParse12, 1);
1338
    UtRegisterTest("DetectDceOpnumTestParse13", DetectDceOpnumTestParse13, 1);
1339
#endif
1340
}
1341
#endif /* UNITTESTS */