Coverage Report

Created: 2026-09-06 07:25

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