Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-parse.c
Line
Count
Source
1
/* Copyright (C) 2007-2021 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 *
23
 * signature parser
24
 */
25
26
#include "suricata-common.h"
27
28
#include "detect.h"
29
#include "detect-engine.h"
30
#include "detect-engine-address.h"
31
#include "detect-engine-port.h"
32
#include "detect-engine-mpm.h"
33
#include "detect-engine-state.h"
34
#include "detect-engine-build.h"
35
36
#include "detect-content.h"
37
#include "detect-bsize.h"
38
#include "detect-pcre.h"
39
#include "detect-uricontent.h"
40
#include "detect-reference.h"
41
#include "detect-ipproto.h"
42
#include "detect-flow.h"
43
#include "detect-app-layer-protocol.h"
44
#include "detect-lua.h"
45
#include "detect-app-layer-event.h"
46
#include "detect-http-method.h"
47
48
#include "pkt-var.h"
49
#include "host.h"
50
#include "util-profiling.h"
51
#include "decode.h"
52
53
#include "flow.h"
54
55
#include "util-rule-vars.h"
56
#include "conf.h"
57
#include "conf-yaml-loader.h"
58
59
#include "app-layer.h"
60
#include "app-layer-protos.h"
61
#include "app-layer-parser.h"
62
#include "app-layer-htp.h"
63
64
#include "util-classification-config.h"
65
#include "util-unittest.h"
66
#include "util-unittest-helper.h"
67
#include "util-debug.h"
68
#include "string.h"
69
#include "detect-parse.h"
70
#include "detect-engine-iponly.h"
71
#include "app-layer-detect-proto.h"
72
73
#include "action-globals.h"
74
#include "util-validate.h"
75
76
/* Table with all filehandler registrations */
77
DetectFileHandlerTableElmt filehandler_table[DETECT_TBLSIZE];
78
79
void DetectFileRegisterFileProtocols(DetectFileHandlerTableElmt *reg)
80
102
{
81
    // file protocols with common file handling
82
102
    typedef struct {
83
102
        AppProto al_proto;
84
102
        int direction;
85
102
        int to_client_progress;
86
102
        int to_server_progress;
87
102
    } DetectFileHandlerProtocol_t;
88
102
    static DetectFileHandlerProtocol_t al_protocols[] = {
89
102
        { .al_proto = ALPROTO_NFS, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
90
102
        { .al_proto = ALPROTO_SMB, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
91
102
        { .al_proto = ALPROTO_FTP, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
92
102
        { .al_proto = ALPROTO_FTPDATA, .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT },
93
102
        { .al_proto = ALPROTO_HTTP1,
94
102
                .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT,
95
102
                .to_client_progress = HTP_RESPONSE_BODY,
96
102
                .to_server_progress = HTP_REQUEST_BODY },
97
102
        { .al_proto = ALPROTO_HTTP2,
98
102
                .direction = SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT,
99
102
                .to_client_progress = HTTP2StateDataServer,
100
102
                .to_server_progress = HTTP2StateDataClient },
101
102
        { .al_proto = ALPROTO_SMTP, .direction = SIG_FLAG_TOSERVER }
102
102
    };
103
104
816
    for (size_t i = 0; i < ARRAY_SIZE(al_protocols); i++) {
105
714
        int direction = al_protocols[i].direction == 0
106
714
                                ? (int)(SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT)
107
714
                                : al_protocols[i].direction;
108
109
714
        if (direction & SIG_FLAG_TOCLIENT) {
110
612
            DetectAppLayerMpmRegister2(reg->name, SIG_FLAG_TOCLIENT, reg->priority,
111
612
                    reg->PrefilterFn, reg->GetData, al_protocols[i].al_proto,
112
612
                    al_protocols[i].to_client_progress);
113
612
            DetectAppLayerInspectEngineRegister2(reg->name, al_protocols[i].al_proto,
114
612
                    SIG_FLAG_TOCLIENT, al_protocols[i].to_client_progress, reg->Callback,
115
612
                    reg->GetData);
116
612
        }
117
714
        if (direction & SIG_FLAG_TOSERVER) {
118
714
            DetectAppLayerMpmRegister2(reg->name, SIG_FLAG_TOSERVER, reg->priority,
119
714
                    reg->PrefilterFn, reg->GetData, al_protocols[i].al_proto,
120
714
                    al_protocols[i].to_server_progress);
121
714
            DetectAppLayerInspectEngineRegister2(reg->name, al_protocols[i].al_proto,
122
714
                    SIG_FLAG_TOSERVER, al_protocols[i].to_server_progress, reg->Callback,
123
714
                    reg->GetData);
124
714
        }
125
714
    }
126
102
}
127
128
/* Table with all SigMatch registrations */
129
SigTableElmt sigmatch_table[DETECT_TBLSIZE];
130
131
extern int sc_set_caps;
132
133
static void SigMatchTransferSigMatchAcrossLists(SigMatch *sm,
134
        SigMatch **src_sm_list, SigMatch **src_sm_list_tail,
135
        SigMatch **dst_sm_list, SigMatch **dst_sm_list_tail);
136
137
/**
138
 * \brief Registration table for file handlers
139
 */
140
/**
141
 * \brief We use this as data to the hash table DetectEngineCtx->dup_sig_hash_table.
142
 */
143
typedef struct SigDuplWrapper_ {
144
    /* the signature we want to wrap */
145
    Signature *s;
146
    /* the signature right before the above signature in the det_ctx->sig_list */
147
    Signature *s_prev;
148
} SigDuplWrapper;
149
150
#define CONFIG_PARTS 8
151
152
#define CONFIG_ACTION 0
153
#define CONFIG_PROTO  1
154
#define CONFIG_SRC    2
155
#define CONFIG_SP     3
156
#define CONFIG_DIREC  4
157
#define CONFIG_DST    5
158
#define CONFIG_DP     6
159
#define CONFIG_OPTS   7
160
161
/** helper structure for sig parsing */
162
typedef struct SignatureParser_ {
163
    char action[DETECT_MAX_RULE_SIZE];
164
    char protocol[DETECT_MAX_RULE_SIZE];
165
    char direction[DETECT_MAX_RULE_SIZE];
166
    char src[DETECT_MAX_RULE_SIZE];
167
    char dst[DETECT_MAX_RULE_SIZE];
168
    char sp[DETECT_MAX_RULE_SIZE];
169
    char dp[DETECT_MAX_RULE_SIZE];
170
    char opts[DETECT_MAX_RULE_SIZE];
171
} SignatureParser;
172
173
const char *DetectListToHumanString(int list)
174
21.4k
{
175
21.4k
#define CASE_CODE_STRING(E, S)  case E: return S; break
176
21.4k
    switch (list) {
177
4.31k
        CASE_CODE_STRING(DETECT_SM_LIST_MATCH, "packet");
178
14.2k
        CASE_CODE_STRING(DETECT_SM_LIST_PMATCH, "payload");
179
84
        CASE_CODE_STRING(DETECT_SM_LIST_BASE64_DATA, "base64_data");
180
2.68k
        CASE_CODE_STRING(DETECT_SM_LIST_POSTMATCH, "postmatch");
181
50
        CASE_CODE_STRING(DETECT_SM_LIST_TMATCH, "tag");
182
0
        CASE_CODE_STRING(DETECT_SM_LIST_SUPPRESS, "suppress");
183
58
        CASE_CODE_STRING(DETECT_SM_LIST_THRESHOLD, "threshold");
184
21.4k
        CASE_CODE_STRING(DETECT_SM_LIST_MAX, "max (internal)");
185
21.4k
    }
186
0
#undef CASE_CODE_STRING
187
0
    return "unknown";
188
21.4k
}
189
190
0
#define CASE_CODE(E)  case E: return #E
191
const char *DetectListToString(int list)
192
0
{
193
0
    switch (list) {
194
0
        CASE_CODE(DETECT_SM_LIST_MATCH);
195
0
        CASE_CODE(DETECT_SM_LIST_PMATCH);
196
0
        CASE_CODE(DETECT_SM_LIST_BASE64_DATA);
197
0
        CASE_CODE(DETECT_SM_LIST_TMATCH);
198
0
        CASE_CODE(DETECT_SM_LIST_POSTMATCH);
199
0
        CASE_CODE(DETECT_SM_LIST_SUPPRESS);
200
0
        CASE_CODE(DETECT_SM_LIST_THRESHOLD);
201
0
        CASE_CODE(DETECT_SM_LIST_MAX);
202
0
    }
203
0
    return "unknown";
204
0
}
205
206
/** \param arg NULL or empty string */
207
int DetectEngineContentModifierBufferSetup(DetectEngineCtx *de_ctx,
208
        Signature *s, const char *arg, int sm_type, int sm_list,
209
        AppProto alproto)
210
133k
{
211
133k
    SigMatch *sm = NULL;
212
133k
    int ret = -1;
213
214
133k
    if (arg != NULL && strcmp(arg, "") != 0) {
215
0
        SCLogError("%s shouldn't be supplied "
216
0
                   "with an argument",
217
0
                sigmatch_table[sm_type].name);
218
0
        goto end;
219
0
    }
220
221
133k
    if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
222
218
        SCLogError("\"%s\" keyword seen "
223
218
                   "with a sticky buffer still set.  Reset sticky buffer "
224
218
                   "with pkt_data before using the modifier.",
225
218
                sigmatch_table[sm_type].name);
226
218
        goto end;
227
218
    }
228
133k
    if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, alproto)) {
229
304
        SCLogError("rule contains conflicting "
230
304
                   "alprotos set");
231
304
        goto end;
232
304
    }
233
234
133k
    sm = DetectGetLastSMByListId(s,
235
133k
            DETECT_SM_LIST_PMATCH, DETECT_CONTENT, -1);
236
133k
    if (sm == NULL) {
237
682
        SCLogError("\"%s\" keyword "
238
682
                   "found inside the rule without a content context.  "
239
682
                   "Please use a \"content\" keyword before using the "
240
682
                   "\"%s\" keyword",
241
682
                sigmatch_table[sm_type].name, sigmatch_table[sm_type].name);
242
682
        goto end;
243
682
    }
244
132k
    DetectContentData *cd = (DetectContentData *)sm->ctx;
245
132k
    if (cd->flags & DETECT_CONTENT_RAWBYTES) {
246
1
        SCLogError("%s rule can not "
247
1
                   "be used with the rawbytes rule keyword",
248
1
                sigmatch_table[sm_type].name);
249
1
        goto end;
250
1
    }
251
132k
    if (cd->flags & DETECT_CONTENT_REPLACE) {
252
0
        SCLogError("%s rule can not "
253
0
                   "be used with the replace rule keyword",
254
0
                sigmatch_table[sm_type].name);
255
0
        goto end;
256
0
    }
257
132k
    if (cd->flags & (DETECT_CONTENT_WITHIN | DETECT_CONTENT_DISTANCE)) {
258
4.94k
        SigMatch *pm = DetectGetLastSMByListPtr(s, sm->prev,
259
4.94k
            DETECT_CONTENT, DETECT_PCRE, -1);
260
4.94k
        if (pm != NULL) {
261
3.99k
            if (pm->type == DETECT_CONTENT) {
262
2.84k
                DetectContentData *tmp_cd = (DetectContentData *)pm->ctx;
263
2.84k
                tmp_cd->flags &= ~DETECT_CONTENT_RELATIVE_NEXT;
264
2.84k
            } else {
265
1.15k
                DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
266
1.15k
                tmp_pd->flags &= ~DETECT_PCRE_RELATIVE_NEXT;
267
1.15k
            }
268
3.99k
        }
269
270
4.94k
        if (s->init_data->curbuf != NULL && (int)s->init_data->curbuf->id == sm_list) {
271
2.09k
            pm = DetectGetLastSMByListPtr(
272
2.09k
                    s, s->init_data->curbuf->tail, DETECT_CONTENT, DETECT_PCRE, -1);
273
2.09k
            if (pm != NULL) {
274
2.09k
                if (pm->type == DETECT_CONTENT) {
275
1.86k
                    DetectContentData *tmp_cd = (DetectContentData *)pm->ctx;
276
1.86k
                    tmp_cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
277
1.86k
                } else {
278
226
                    DetectPcreData *tmp_pd = (DetectPcreData *)pm->ctx;
279
226
                    tmp_pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
280
226
                }
281
2.09k
            }
282
2.09k
        }
283
4.94k
    }
284
132k
    s->alproto = alproto;
285
132k
    s->flags |= SIG_FLAG_APPLAYER;
286
287
132k
    if (s->init_data->curbuf == NULL || (int)s->init_data->curbuf->id != sm_list) {
288
67.8k
        if (s->init_data->curbuf != NULL && s->init_data->curbuf->head == NULL) {
289
166
            SCLogError("no matches for previous buffer");
290
166
            return -1;
291
166
        }
292
67.8k
        bool reuse_buffer = false;
293
67.7k
        if (s->init_data->curbuf != NULL && (int)s->init_data->curbuf->id != sm_list) {
294
22.6k
            for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
295
17.1k
                if (s->init_data->buffers[x].id == (uint32_t)sm_list) {
296
5.79k
                    s->init_data->curbuf = &s->init_data->buffers[x];
297
5.79k
                    reuse_buffer = true;
298
5.79k
                    break;
299
5.79k
                }
300
17.1k
            }
301
11.2k
        }
302
303
67.7k
        if (!reuse_buffer) {
304
61.9k
            if (SignatureInitDataBufferCheckExpand(s) < 0) {
305
2
                SCLogError("failed to expand rule buffer array");
306
2
                return -1;
307
2
            }
308
309
            /* initialize a new buffer */
310
61.9k
            s->init_data->curbuf = &s->init_data->buffers[s->init_data->buffer_index++];
311
61.9k
            s->init_data->curbuf->id = sm_list;
312
61.9k
            s->init_data->curbuf->head = NULL;
313
61.9k
            s->init_data->curbuf->tail = NULL;
314
61.9k
            SCLogDebug("idx %u list %d set up curbuf %p s->init_data->buffer_index %u",
315
61.9k
                    s->init_data->buffer_index - 1, sm_list, s->init_data->curbuf,
316
61.9k
                    s->init_data->buffer_index);
317
61.9k
        }
318
67.7k
    }
319
320
    /* transfer the sm from the pmatch list to sm_list */
321
132k
    SigMatchTransferSigMatchAcrossLists(sm, &s->init_data->smlists[DETECT_SM_LIST_PMATCH],
322
132k
            &s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH], &s->init_data->curbuf->head,
323
132k
            &s->init_data->curbuf->tail);
324
325
132k
    if (sm->type == DETECT_CONTENT) {
326
132k
        s->init_data->max_content_list_id =
327
132k
                MAX(s->init_data->max_content_list_id, (uint32_t)sm_list);
328
132k
    }
329
330
132k
    ret = 0;
331
133k
 end:
332
133k
    return ret;
333
132k
}
334
335
SigMatch *SigMatchAlloc(void)
336
3.37M
{
337
3.37M
    SigMatch *sm = SCMalloc(sizeof(SigMatch));
338
3.37M
    if (unlikely(sm == NULL))
339
0
        return NULL;
340
341
3.37M
    memset(sm, 0, sizeof(SigMatch));
342
3.37M
    sm->prev = NULL;
343
3.37M
    sm->next = NULL;
344
3.37M
    return sm;
345
3.37M
}
346
347
/** \brief free a SigMatch
348
 *  \param sm SigMatch to free.
349
 */
350
void SigMatchFree(DetectEngineCtx *de_ctx, SigMatch *sm)
351
3.37M
{
352
3.37M
    if (sm == NULL)
353
0
        return;
354
355
    /** free the ctx, for that we call the Free func */
356
3.37M
    if (sm->ctx != NULL) {
357
2.68M
        if (sigmatch_table[sm->type].Free != NULL) {
358
2.68M
            sigmatch_table[sm->type].Free(de_ctx, sm->ctx);
359
2.68M
        }
360
2.68M
    }
361
3.37M
    SCFree(sm);
362
3.37M
}
363
364
static enum DetectKeywordId SigTableGetIndex(const SigTableElmt *e)
365
5.03M
{
366
5.03M
    const SigTableElmt *table = &sigmatch_table[0];
367
5.03M
    ptrdiff_t offset = e - table;
368
5.03M
    BUG_ON(offset >= DETECT_TBLSIZE);
369
5.03M
    return (enum DetectKeywordId)offset;
370
5.03M
}
371
372
/* Get the detection module by name */
373
static SigTableElmt *SigTableGet(char *name)
374
12.4M
{
375
12.4M
    SigTableElmt *st = NULL;
376
12.4M
    int i = 0;
377
378
765M
    for (i = 0; i < DETECT_TBLSIZE; i++) {
379
765M
        st = &sigmatch_table[i];
380
381
765M
        if (st->name != NULL) {
382
750M
            if (strcasecmp(name,st->name) == 0)
383
11.8M
                return st;
384
738M
            if (st->alias != NULL && strcasecmp(name,st->alias) == 0)
385
172k
                return st;
386
738M
        }
387
765M
    }
388
389
436k
    return NULL;
390
12.4M
}
391
392
bool SigMatchSilentErrorEnabled(const DetectEngineCtx *de_ctx,
393
        const enum DetectKeywordId id)
394
0
{
395
0
    return de_ctx->sm_types_silent_error[id];
396
0
}
397
398
bool SigMatchStrictEnabled(const enum DetectKeywordId id)
399
69.8k
{
400
69.8k
    if (id < DETECT_TBLSIZE) {
401
69.8k
        return ((sigmatch_table[id].flags & SIGMATCH_STRICT_PARSING) != 0);
402
69.8k
    }
403
0
    return false;
404
69.8k
}
405
406
void SigTableApplyStrictCommandLineOption(const char *str)
407
73
{
408
73
    if (str == NULL) {
409
        /* nothing to be done */
410
73
        return;
411
73
    }
412
413
    /* "all" just sets the flag for each keyword */
414
0
    if (strcmp(str, "all") == 0) {
415
0
        for (int i = 0; i < DETECT_TBLSIZE; i++) {
416
0
            SigTableElmt *st = &sigmatch_table[i];
417
0
            st->flags |= SIGMATCH_STRICT_PARSING;
418
0
        }
419
0
        return;
420
0
    }
421
422
0
    char *copy = SCStrdup(str);
423
0
    if (copy == NULL)
424
0
        FatalError("could not duplicate opt string");
425
426
0
    char *xsaveptr = NULL;
427
0
    char *key = strtok_r(copy, ",", &xsaveptr);
428
0
    while (key != NULL) {
429
0
        SigTableElmt *st = SigTableGet(key);
430
0
        if (st != NULL) {
431
0
            st->flags |= SIGMATCH_STRICT_PARSING;
432
0
        } else {
433
0
            SCLogWarning("'strict' command line "
434
0
                         "argument '%s' not found",
435
0
                    key);
436
0
        }
437
0
        key = strtok_r(NULL, ",", &xsaveptr);
438
0
    }
439
440
0
    SCFree(copy);
441
0
}
442
443
/**
444
 * \brief Append a SigMatch to the list type.
445
 *
446
 * \param s    Signature.
447
 * \param new  The sig match to append.
448
 * \param list The list to append to.
449
 */
450
void SigMatchAppendSMToList(Signature *s, SigMatch *new, const int list)
451
1.90M
{
452
1.90M
    if (new->type == DETECT_CONTENT) {
453
597k
        s->init_data->max_content_list_id = MAX(s->init_data->max_content_list_id, (uint32_t)list);
454
597k
    }
455
456
1.90M
    SCLogDebug("s:%p new:%p list:%d: %s, s->init_data->list_set %s s->init_data->list %d", s, new,
457
1.90M
            list, sigmatch_table[new->type].name, BOOL2STR(s->init_data->list_set),
458
1.90M
            s->init_data->list);
459
460
1.90M
    if (list < DETECT_SM_LIST_MAX) {
461
1.17M
        if (s->init_data->smlists[list] == NULL) {
462
775k
            s->init_data->smlists[list] = new;
463
775k
            s->init_data->smlists_tail[list] = new;
464
775k
            new->next = NULL;
465
775k
            new->prev = NULL;
466
775k
        } else {
467
396k
            SigMatch *cur = s->init_data->smlists_tail[list];
468
396k
            cur->next = new;
469
396k
            new->prev = cur;
470
396k
            new->next = NULL;
471
396k
            s->init_data->smlists_tail[list] = new;
472
396k
        }
473
1.17M
        new->idx = s->init_data->sm_cnt;
474
1.17M
        s->init_data->sm_cnt++;
475
476
1.17M
    } else {
477
        /* app-layer-events (and possibly others?) can get here w/o a "list"
478
         * already set up. */
479
480
        /* unset any existing list if it isn't the same as the new */
481
731k
        if (s->init_data->list != DETECT_SM_LIST_NOTSET && list != s->init_data->list) {
482
14.1k
            SCLogDebug("reset: list %d != s->init_data->list %d", list, s->init_data->list);
483
14.1k
            s->init_data->list = DETECT_SM_LIST_NOTSET;
484
14.1k
        }
485
486
731k
        if (s->init_data->curbuf != NULL && (int)s->init_data->curbuf->id != list) {
487
46.9k
            for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
488
26.3k
                if (s->init_data->buffers[x].id == (uint32_t)list &&
489
2.91k
                        !s->init_data->buffers[x].multi_capable) {
490
2.47k
                    SCLogDebug("reusing buffer %u as it isn't multi-capable", x);
491
2.47k
                    s->init_data->curbuf = &s->init_data->buffers[x];
492
2.47k
                    break;
493
2.47k
                }
494
26.3k
            }
495
23.1k
        }
496
497
731k
        if ((s->init_data->curbuf != NULL && (int)s->init_data->curbuf->id != list) ||
498
711k
                s->init_data->curbuf == NULL) {
499
344k
            if (SignatureInitDataBufferCheckExpand(s) < 0) {
500
2
                SCLogError("failed to expand rule buffer array");
501
2
                s->init_data->init_flags |= SIG_FLAG_INIT_OVERFLOW;
502
                // SignatureInitDataBufferCheckExpand should not fail in this case
503
2
                DEBUG_VALIDATE_BUG_ON(s->init_data->curbuf == NULL);
504
                // keep curbuf even with wrong id as we error on this signature
505
344k
            } else {
506
                /* initialize new buffer */
507
344k
                s->init_data->curbuf = &s->init_data->buffers[s->init_data->buffer_index++];
508
344k
                s->init_data->curbuf->id = list;
509
                /* buffer set up by sigmatch is tracked in case we add a stickybuffer for the
510
                 * same list. */
511
344k
                s->init_data->curbuf->sm_init = true;
512
344k
                SCLogDebug("s->init_data->buffer_index %u", s->init_data->buffer_index);
513
344k
            }
514
344k
        }
515
731k
        BUG_ON(s->init_data->curbuf == NULL);
516
517
731k
        new->prev = s->init_data->curbuf->tail;
518
731k
        if (s->init_data->curbuf->tail)
519
138k
            s->init_data->curbuf->tail->next = new;
520
731k
        if (s->init_data->curbuf->head == NULL)
521
593k
            s->init_data->curbuf->head = new;
522
731k
        s->init_data->curbuf->tail = new;
523
731k
        new->idx = s->init_data->sm_cnt;
524
731k
        s->init_data->sm_cnt++;
525
731k
        SCLogDebug("appended %s to list %d, rule pos %u (s->init_data->list %d)",
526
731k
                sigmatch_table[new->type].name, list, new->idx, s->init_data->list);
527
528
3.21M
        for (SigMatch *sm = s->init_data->curbuf->head; sm != NULL; sm = sm->next) {
529
2.48M
            SCLogDebug("buf:%p: id:%u: '%s' pos %u", s->init_data->curbuf, s->init_data->curbuf->id,
530
2.48M
                    sigmatch_table[sm->type].name, sm->idx);
531
2.48M
        }
532
731k
    }
533
1.90M
}
534
535
void SigMatchRemoveSMFromList(Signature *s, SigMatch *sm, int sm_list)
536
8.74k
{
537
8.74k
    if (sm == s->init_data->smlists[sm_list]) {
538
5.76k
        s->init_data->smlists[sm_list] = sm->next;
539
5.76k
    }
540
8.74k
    if (sm == s->init_data->smlists_tail[sm_list]) {
541
5.33k
        s->init_data->smlists_tail[sm_list] = sm->prev;
542
5.33k
    }
543
8.74k
    if (sm->prev != NULL)
544
2.97k
        sm->prev->next = sm->next;
545
8.74k
    if (sm->next != NULL)
546
3.40k
        sm->next->prev = sm->prev;
547
548
8.74k
    return;
549
8.74k
}
550
551
/**
552
 * \brief Returns a pointer to the last SigMatch instance of a particular type
553
 *        in a Signature of the payload list.
554
 *
555
 * \param s    Pointer to the tail of the sigmatch list
556
 * \param type SigMatch type which has to be searched for in the Signature.
557
 *
558
 * \retval match Pointer to the last SigMatch instance of type 'type'.
559
 */
560
static SigMatch *SigMatchGetLastSMByType(SigMatch *sm, int type)
561
2.27M
{
562
7.31M
    while (sm != NULL) {
563
6.26M
        if (sm->type == type) {
564
1.23M
            return sm;
565
1.23M
        }
566
5.03M
        sm = sm->prev;
567
5.03M
    }
568
569
1.04M
    return NULL;
570
2.27M
}
571
572
/** \brief get the last SigMatch from lists that support
573
 *         MPM.
574
 *  \note only supports the lists that are registered through
575
 *        DetectBufferTypeSupportsMpm().
576
 */
577
SigMatch *DetectGetLastSMFromMpmLists(const DetectEngineCtx *de_ctx, const Signature *s)
578
38.8k
{
579
38.8k
    SigMatch *sm_last = NULL;
580
38.8k
    SigMatch *sm_new;
581
38.8k
    uint32_t sm_type;
582
583
98.2k
    for (uint32_t i = 0; i < s->init_data->buffer_index; i++) {
584
59.3k
        const int id = s->init_data->buffers[i].id;
585
59.3k
        if (DetectEngineBufferTypeSupportsMpmGetById(de_ctx, id)) {
586
58.8k
            sm_new = DetectGetLastSMByListPtr(s, s->init_data->buffers[i].tail, DETECT_CONTENT, -1);
587
58.8k
            if (sm_new == NULL)
588
5.08k
                continue;
589
53.7k
            if (sm_last == NULL || sm_new->idx > sm_last->idx)
590
50.2k
                sm_last = sm_new;
591
53.7k
        }
592
59.3k
    }
593
    /* otherwise brute force it */
594
310k
    for (sm_type = 0; sm_type < DETECT_SM_LIST_MAX; sm_type++) {
595
271k
        if (!DetectEngineBufferTypeSupportsMpmGetById(de_ctx, sm_type))
596
271k
            continue;
597
0
        SigMatch *sm_list = s->init_data->smlists_tail[sm_type];
598
0
        sm_new = SigMatchGetLastSMByType(sm_list, DETECT_CONTENT);
599
0
        if (sm_new == NULL)
600
0
            continue;
601
0
        if (sm_last == NULL || sm_new->idx > sm_last->idx)
602
0
            sm_last = sm_new;
603
0
    }
604
605
38.8k
    return sm_last;
606
38.8k
}
607
608
/**
609
 * \brief Returns the sm with the largest index (added latest) from the lists
610
 *        passed to us.
611
 *
612
 * \retval Pointer to Last sm.
613
 */
614
SigMatch *DetectGetLastSMFromLists(const Signature *s, ...)
615
423k
{
616
423k
    SigMatch *sm_last = NULL;
617
423k
    SigMatch *sm_new;
618
619
423k
    SCLogDebug("s->init_data->buffer_index %u", s->init_data->buffer_index);
620
679k
    for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
621
256k
        if (s->init_data->list != DETECT_SM_LIST_NOTSET &&
622
142k
                s->init_data->list != (int)s->init_data->buffers[x].id) {
623
24.5k
            SCLogDebug("skip x %u s->init_data->list %d (int)s->init_data->buffers[x].id %d", x,
624
24.5k
                    s->init_data->list, (int)s->init_data->buffers[x].id);
625
626
24.5k
            continue;
627
24.5k
        }
628
231k
        int sm_type;
629
231k
        va_list ap;
630
231k
        va_start(ap, s);
631
632
560k
        for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int)) {
633
328k
            sm_new = SigMatchGetLastSMByType(s->init_data->buffers[x].tail, sm_type);
634
328k
            if (sm_new == NULL)
635
135k
                continue;
636
193k
            if (sm_last == NULL || sm_new->idx > sm_last->idx)
637
188k
                sm_last = sm_new;
638
193k
        }
639
231k
        va_end(ap);
640
231k
    }
641
642
3.38M
    for (int buf_type = 0; buf_type < DETECT_SM_LIST_MAX; buf_type++) {
643
2.96M
        if (s->init_data->smlists[buf_type] == NULL)
644
2.53M
            continue;
645
425k
        if (s->init_data->list != DETECT_SM_LIST_NOTSET &&
646
69.1k
            buf_type != s->init_data->list)
647
67.1k
            continue;
648
649
357k
        int sm_type;
650
357k
        va_list ap;
651
357k
        va_start(ap, s);
652
653
982k
        for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
654
624k
        {
655
624k
            sm_new = SigMatchGetLastSMByType(s->init_data->smlists_tail[buf_type], sm_type);
656
624k
            if (sm_new == NULL)
657
371k
                continue;
658
252k
            if (sm_last == NULL || sm_new->idx > sm_last->idx)
659
227k
                sm_last = sm_new;
660
252k
        }
661
357k
        va_end(ap);
662
357k
    }
663
664
423k
    return sm_last;
665
423k
}
666
667
/**
668
 * \brief Returns the sm with the largest index (added last) from the list
669
 *        passed to us as a pointer.
670
 *
671
 * \param sm_list pointer to the SigMatch we should look before
672
 * \param va_args list of keyword types terminated by -1
673
 *
674
 * \retval sm_last to last sm.
675
 */
676
SigMatch *DetectGetLastSMByListPtr(const Signature *s, SigMatch *sm_list, ...)
677
271k
{
678
271k
    SigMatch *sm_last = NULL;
679
271k
    SigMatch *sm_new;
680
271k
    int sm_type;
681
682
271k
    va_list ap;
683
271k
    va_start(ap, sm_list);
684
685
754k
    for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int))
686
483k
    {
687
483k
        sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
688
483k
        if (sm_new == NULL)
689
240k
            continue;
690
242k
        if (sm_last == NULL || sm_new->idx > sm_last->idx)
691
228k
            sm_last = sm_new;
692
242k
    }
693
694
271k
    va_end(ap);
695
696
271k
    return sm_last;
697
271k
}
698
699
/**
700
 * \brief Returns the sm with the largest index (added last) from the list
701
 *        passed to us as an id.
702
 *
703
 * \param list_id id of the list to be searched
704
 * \param va_args list of keyword types terminated by -1
705
 *
706
 * \retval sm_last to last sm.
707
 */
708
SigMatch *DetectGetLastSMByListId(const Signature *s, int list_id, ...)
709
256k
{
710
256k
    SigMatch *sm_last = NULL;
711
256k
    SigMatch *sm_new;
712
256k
    int sm_type;
713
714
256k
    if ((uint32_t)list_id >= DETECT_SM_LIST_MAX) {
715
89.0k
        for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
716
55.6k
            sm_new = s->init_data->buffers[x].tail;
717
55.6k
            if (sm_new == NULL)
718
21.3k
                continue;
719
720
34.3k
            va_list ap;
721
34.3k
            va_start(ap, list_id);
722
723
68.6k
            for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int)) {
724
34.3k
                sm_new = SigMatchGetLastSMByType(s->init_data->buffers[x].tail, sm_type);
725
34.3k
                if (sm_new == NULL)
726
15.2k
                    continue;
727
19.0k
                if (sm_last == NULL || sm_new->idx > sm_last->idx)
728
18.0k
                    sm_last = sm_new;
729
19.0k
            }
730
731
34.3k
            va_end(ap);
732
34.3k
        }
733
223k
    } else {
734
223k
        SigMatch *sm_list = s->init_data->smlists_tail[list_id];
735
223k
        if (sm_list == NULL)
736
55.2k
            return NULL;
737
738
168k
        va_list ap;
739
168k
        va_start(ap, list_id);
740
741
336k
        for (sm_type = va_arg(ap, int); sm_type != -1; sm_type = va_arg(ap, int)) {
742
168k
            sm_new = SigMatchGetLastSMByType(sm_list, sm_type);
743
168k
            if (sm_new == NULL)
744
11.4k
                continue;
745
156k
            if (sm_last == NULL || sm_new->idx > sm_last->idx)
746
156k
                sm_last = sm_new;
747
156k
        }
748
749
168k
        va_end(ap);
750
168k
    }
751
201k
    return sm_last;
752
256k
}
753
754
/**
755
 * \brief Returns the sm with the largest index (added latest) from this sig
756
 *
757
 * \retval sm_last Pointer to last sm
758
 */
759
SigMatch *DetectGetLastSM(const Signature *s)
760
78.1k
{
761
78.1k
    SigMatch *sm_last = NULL;
762
78.1k
    SigMatch *sm_new;
763
764
90.5k
    for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
765
12.4k
        sm_new = s->init_data->buffers[x].tail;
766
12.4k
        if (sm_new == NULL)
767
977
            continue;
768
11.4k
        if (sm_last == NULL || sm_new->idx > sm_last->idx)
769
8.43k
            sm_last = sm_new;
770
11.4k
    }
771
772
625k
    for (int i = 0; i < DETECT_SM_LIST_MAX; i++) {
773
546k
        sm_new = s->init_data->smlists_tail[i];
774
546k
        if (sm_new == NULL)
775
462k
            continue;
776
84.6k
        if (sm_last == NULL || sm_new->idx > sm_last->idx)
777
75.9k
            sm_last = sm_new;
778
84.6k
    }
779
780
78.1k
    return sm_last;
781
78.1k
}
782
783
static void SigMatchTransferSigMatchAcrossLists(SigMatch *sm,
784
        SigMatch **src_sm_list, SigMatch **src_sm_list_tail,
785
        SigMatch **dst_sm_list, SigMatch **dst_sm_list_tail)
786
65.8k
{
787
    /* we won't do any checks for args */
788
789
65.8k
    if (sm->prev != NULL)
790
22.7k
        sm->prev->next = sm->next;
791
65.8k
    if (sm->next != NULL)
792
1.24k
        sm->next->prev = sm->prev;
793
794
65.8k
    if (sm == *src_sm_list)
795
43.0k
        *src_sm_list = sm->next;
796
65.8k
    if (sm == *src_sm_list_tail)
797
64.5k
        *src_sm_list_tail = sm->prev;
798
799
65.8k
    if (*dst_sm_list == NULL) {
800
35.8k
        *dst_sm_list = sm;
801
35.8k
        *dst_sm_list_tail = sm;
802
35.8k
        sm->next = NULL;
803
35.8k
        sm->prev = NULL;
804
35.8k
    } else {
805
29.9k
        SigMatch *cur = *dst_sm_list_tail;
806
29.9k
        cur->next = sm;
807
29.9k
        sm->prev = cur;
808
29.9k
        sm->next = NULL;
809
29.9k
        *dst_sm_list_tail = sm;
810
29.9k
    }
811
812
65.8k
    return;
813
65.8k
}
814
815
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
816
74.7k
{
817
74.7k
    if (key_sm == NULL)
818
0
        return -1;
819
820
98.0k
    for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
821
57.6k
        const SigMatch *sm = s->init_data->buffers[x].head;
822
246k
        while (sm != NULL) {
823
223k
            if (sm == key_sm)
824
34.3k
                return s->init_data->buffers[x].id;
825
188k
            sm = sm->next;
826
188k
        }
827
57.6k
    }
828
829
81.1k
    for (int list = 0; list < DETECT_SM_LIST_MAX; list++) {
830
81.1k
        const SigMatch *sm = s->init_data->smlists[list];
831
328k
        while (sm != NULL) {
832
287k
            if (sm == key_sm)
833
40.4k
                return list;
834
247k
            sm = sm->next;
835
247k
        }
836
81.1k
    }
837
838
0
    SCLogError("Unable to find the sm in any of the "
839
0
               "sm lists");
840
0
    return -1;
841
40.4k
}
842
843
static int SigParseOptions(DetectEngineCtx *de_ctx, Signature *s, char *optstr, char *output,
844
        size_t output_size, bool requires)
845
18.9M
{
846
18.9M
    SigTableElmt *st = NULL;
847
18.9M
    char *optname = NULL;
848
18.9M
    char *optvalue = NULL;
849
850
    /* Trim leading space. */
851
18.9M
    while (isblank(*optstr)) {
852
15.7M
        optstr++;
853
15.7M
    }
854
855
    /* Look for the end of this option, handling escaped semicolons. */
856
18.9M
    char *optend = optstr;
857
18.9M
    for (;;) {
858
18.9M
        optend = strchr(optend, ';');
859
18.9M
        if (optend == NULL) {
860
224k
            SCLogError("no terminating \";\" found");
861
224k
            goto error;
862
224k
        }
863
18.7M
        else if (optend > optstr && *(optend -1 ) == '\\') {
864
12.1k
            optend++;
865
18.6M
        } else {
866
18.6M
            break;
867
18.6M
        }
868
18.9M
    }
869
18.6M
    *(optend++) = '\0';
870
871
    /* Find the start of the option value. */
872
18.6M
    char *optvalptr = strchr(optstr, ':');
873
18.6M
    if (optvalptr) {
874
15.8M
        *(optvalptr++) = '\0';
875
876
        /* Trim trailing space from name. */
877
16.1M
        for (size_t i = strlen(optvalptr); i > 0; i--) {
878
16.1M
            if (isblank(optvalptr[i - 1])) {
879
308k
                optvalptr[i - 1] = '\0';
880
15.7M
            } else {
881
15.7M
                break;
882
15.7M
            }
883
16.1M
        }
884
885
15.8M
        optvalue = optvalptr;
886
15.8M
    }
887
888
    /* Trim trailing space from name. */
889
18.9M
    for (size_t i = strlen(optstr); i > 0; i--) {
890
18.8M
        if (isblank(optstr[i - 1])) {
891
237k
            optstr[i - 1] = '\0';
892
18.6M
        } else {
893
18.6M
            break;
894
18.6M
        }
895
18.8M
    }
896
18.6M
    optname = optstr;
897
898
    /* Check for options that are only to be processed during the
899
     * first "requires" pass. */
900
18.6M
    bool requires_only = strcasecmp(optname, "requires") == 0 || strcasecmp(optname, "sid") == 0;
901
18.6M
    if ((requires && !requires_only) || (!requires && requires_only)) {
902
11.4M
        goto finish;
903
11.4M
    }
904
905
    /* Call option parsing */
906
7.28M
    st = SigTableGet(optname);
907
7.28M
    if (st == NULL || st->Setup == NULL) {
908
260k
        SCLogError("unknown rule keyword '%s'.", optname);
909
260k
        goto error;
910
260k
    }
911
912
7.02M
    if (!(st->flags & (SIGMATCH_NOOPT|SIGMATCH_OPTIONAL_OPT))) {
913
6.35M
        if (optvalue == NULL || strlen(optvalue) == 0) {
914
5.45k
            SCLogError(
915
5.45k
                    "invalid formatting or malformed option to %s keyword: '%s'", optname, optstr);
916
5.45k
            goto error;
917
5.45k
        }
918
6.35M
    } else if (st->flags & SIGMATCH_NOOPT) {
919
599k
        if (optvalue && strlen(optvalue)) {
920
84
            SCLogError("unexpected option to %s keyword: '%s'", optname, optstr);
921
84
            goto error;
922
84
        }
923
599k
    }
924
7.01M
    s->init_data->negated = false;
925
926
7.01M
    if (st->flags & SIGMATCH_INFO_DEPRECATED) {
927
2.66k
#define URL "https://suricata.io/our-story/deprecation-policy/"
928
2.66k
        if (st->alternative == 0)
929
0
            SCLogWarning("keyword '%s' is deprecated "
930
2.66k
                         "and will be removed soon. See %s",
931
2.66k
                    st->name, URL);
932
2.66k
        else
933
2.66k
            SCLogWarning("keyword '%s' is deprecated "
934
2.66k
                         "and will be removed soon. Use '%s' instead. "
935
2.66k
                         "See %s",
936
2.66k
                    st->name, sigmatch_table[st->alternative].name, URL);
937
2.66k
#undef URL
938
2.66k
    }
939
940
7.01M
    int setup_ret = 0;
941
942
    /* Validate double quoting, trimming trailing white space along the way. */
943
7.01M
    if (optvalue != NULL && strlen(optvalue) > 0) {
944
6.36M
        size_t ovlen = strlen(optvalue);
945
6.36M
        char *ptr = optvalue;
946
947
        /* skip leading whitespace */
948
6.66M
        while (ovlen > 0) {
949
6.66M
            if (!isblank(*ptr))
950
6.36M
                break;
951
298k
            ptr++;
952
298k
            ovlen--;
953
298k
        }
954
6.36M
        if (ovlen == 0) {
955
0
            SCLogError("invalid formatting or malformed option to %s keyword: \'%s\'", optname,
956
0
                    optstr);
957
0
            goto error;
958
0
        }
959
960
        /* see if value is negated */
961
6.36M
        if ((st->flags & SIGMATCH_HANDLE_NEGATION) && *ptr == '!') {
962
49.4k
            s->init_data->negated = true;
963
49.4k
            ptr++;
964
49.4k
            ovlen--;
965
49.4k
        }
966
        /* skip more whitespace */
967
6.37M
        while (ovlen > 0) {
968
6.37M
            if (!isblank(*ptr))
969
6.36M
                break;
970
3.02k
            ptr++;
971
3.02k
            ovlen--;
972
3.02k
        }
973
6.36M
        if (ovlen == 0) {
974
455
            SCLogError("invalid formatting or malformed option to %s keyword: \'%s\'", optname,
975
455
                    optstr);
976
455
            goto error;
977
455
        }
978
        /* if quoting is mandatory, enforce it */
979
6.36M
        if (st->flags & SIGMATCH_QUOTES_MANDATORY && ovlen && *ptr != '"') {
980
8.15k
            SCLogError("invalid formatting to %s keyword: "
981
8.15k
                       "value must be double quoted \'%s\'",
982
8.15k
                    optname, optstr);
983
8.15k
            goto error;
984
8.15k
        }
985
986
6.36M
        if ((st->flags & (SIGMATCH_QUOTES_OPTIONAL|SIGMATCH_QUOTES_MANDATORY))
987
2.02M
                && ovlen && *ptr == '"')
988
1.68M
        {
989
1.68M
            for (; ovlen > 0; ovlen--) {
990
1.68M
                if (isblank(ptr[ovlen - 1])) {
991
0
                    ptr[ovlen - 1] = '\0';
992
1.68M
                } else {
993
1.68M
                    break;
994
1.68M
                }
995
1.68M
            }
996
1.68M
            if (ovlen && ptr[ovlen - 1] != '"') {
997
45.0k
                SCLogError("bad option value formatting (possible missing semicolon) "
998
45.0k
                           "for keyword %s: \'%s\'",
999
45.0k
                        optname, optvalue);
1000
45.0k
                goto error;
1001
45.0k
            }
1002
1.63M
            if (ovlen > 1) {
1003
                /* strip leading " */
1004
1.60M
                ptr++;
1005
1.60M
                ovlen--;
1006
1.60M
                ptr[ovlen - 1] = '\0';
1007
1.60M
                ovlen--;
1008
1.60M
            }
1009
1.63M
            if (ovlen == 0) {
1010
316
                SCLogError("bad input "
1011
316
                           "for keyword %s: \'%s\'",
1012
316
                        optname, optvalue);
1013
316
                goto error;
1014
316
            }
1015
4.67M
        } else {
1016
4.67M
            if (*ptr == '"') {
1017
829
                SCLogError(
1018
829
                        "quotes on %s keyword that doesn't support them: \'%s\'", optname, optstr);
1019
829
                goto error;
1020
829
            }
1021
4.67M
        }
1022
        /* setup may or may not add a new SigMatch to the list */
1023
6.31M
        setup_ret = st->Setup(de_ctx, s, ptr);
1024
6.31M
    } else {
1025
        /* setup may or may not add a new SigMatch to the list */
1026
646k
        setup_ret = st->Setup(de_ctx, s, NULL);
1027
646k
    }
1028
6.96M
    if (setup_ret < 0 || (s->init_data->init_flags & SIG_FLAG_INIT_OVERFLOW)) {
1029
584k
        SCLogDebug("\"%s\" failed to setup", st->name);
1030
584k
        if (s->init_data->init_flags & SIG_FLAG_INIT_OVERFLOW) {
1031
2
            SCLogError("rule %u tries to use too many buffers", s->id);
1032
2
        }
1033
1034
        /* handle 'silent' error case */
1035
584k
        if (setup_ret == -2) {
1036
0
            enum DetectKeywordId idx = SigTableGetIndex(st);
1037
0
            if (de_ctx->sm_types_silent_error[idx] == false) {
1038
0
                de_ctx->sm_types_silent_error[idx] = true;
1039
0
                return -1;
1040
0
            }
1041
0
            return -2;
1042
0
        }
1043
584k
        return setup_ret;
1044
584k
    }
1045
6.37M
    s->init_data->negated = false;
1046
1047
17.7M
finish:
1048
17.7M
    if (strlen(optend) > 0) {
1049
14.5M
        strlcpy(output, optend, output_size);
1050
14.5M
        return 1;
1051
14.5M
    }
1052
1053
3.18M
    return 0;
1054
1055
544k
error:
1056
544k
    return -1;
1057
17.7M
}
1058
1059
/** \brief Parse address string and update signature
1060
 *
1061
 *  \retval 0 ok, -1 error
1062
 */
1063
static int SigParseAddress(DetectEngineCtx *de_ctx,
1064
        Signature *s, const char *addrstr, char flag)
1065
5.99M
{
1066
5.99M
    SCLogDebug("Address Group \"%s\" to be parsed now", addrstr);
1067
1068
    /* pass on to the address(list) parser */
1069
5.99M
    if (flag == 0) {
1070
3.03M
        if (strcasecmp(addrstr, "any") == 0)
1071
2.62M
            s->flags |= SIG_FLAG_SRC_ANY;
1072
1073
3.03M
        s->init_data->src = DetectParseAddress(de_ctx, addrstr,
1074
3.03M
                &s->init_data->src_contains_negation);
1075
3.03M
        if (s->init_data->src == NULL)
1076
61.3k
            goto error;
1077
3.03M
    } else {
1078
2.96M
        if (strcasecmp(addrstr, "any") == 0)
1079
2.61M
            s->flags |= SIG_FLAG_DST_ANY;
1080
1081
2.96M
        s->init_data->dst = DetectParseAddress(de_ctx, addrstr,
1082
2.96M
                &s->init_data->dst_contains_negation);
1083
2.96M
        if (s->init_data->dst == NULL)
1084
114k
            goto error;
1085
2.96M
    }
1086
1087
5.82M
    return 0;
1088
1089
175k
error:
1090
175k
    return -1;
1091
5.99M
}
1092
1093
/**
1094
 * \brief Parses the protocol supplied by the Signature.
1095
 *
1096
 *        http://www.iana.org/assignments/protocol-numbers
1097
 *
1098
 * \param s        Pointer to the Signature instance to which the parsed
1099
 *                 protocol has to be added.
1100
 * \param protostr Pointer to the character string containing the protocol name.
1101
 *
1102
 * \retval  0 On successfully parsing the protocol sent as the argument.
1103
 * \retval -1 On failure
1104
 */
1105
static int SigParseProto(Signature *s, const char *protostr)
1106
1.88M
{
1107
1.88M
    SCEnter();
1108
1109
1.88M
    int r = DetectProtoParse(&s->proto, (char *)protostr);
1110
1.88M
    if (r < 0) {
1111
877k
        s->alproto = AppLayerGetProtoByName((char *)protostr);
1112
        /* indicate that the signature is app-layer */
1113
877k
        if (s->alproto != ALPROTO_UNKNOWN) {
1114
823k
            s->flags |= SIG_FLAG_APPLAYER;
1115
1116
823k
            AppLayerProtoDetectSupportedIpprotos(s->alproto, s->proto.proto);
1117
823k
        }
1118
53.1k
        else {
1119
53.1k
            SCLogError("protocol \"%s\" cannot be used "
1120
53.1k
                       "in a signature.  Either detection for this protocol "
1121
53.1k
                       "is not yet supported OR detection has been disabled for "
1122
53.1k
                       "protocol through the yaml option "
1123
53.1k
                       "app-layer.protocols.%s.detection-enabled",
1124
53.1k
                    protostr, protostr);
1125
53.1k
            SCReturnInt(-1);
1126
53.1k
        }
1127
877k
    }
1128
1129
    /* if any of these flags are set they are set in a mutually exclusive
1130
     * manner */
1131
1.83M
    if (s->proto.flags & DETECT_PROTO_ONLY_PKT) {
1132
80.1k
        s->flags |= SIG_FLAG_REQUIRE_PACKET;
1133
1.75M
    } else if (s->proto.flags & DETECT_PROTO_ONLY_STREAM) {
1134
15.6k
        s->flags |= SIG_FLAG_REQUIRE_STREAM;
1135
15.6k
    }
1136
1137
1.83M
    SCReturnInt(0);
1138
1.88M
}
1139
1140
/**
1141
 * \brief Parses the port(source or destination) field, from a Signature.
1142
 *
1143
 * \param s       Pointer to the signature which has to be updated with the
1144
 *                port information.
1145
 * \param portstr Pointer to the character string containing the port info.
1146
 * \param         Flag which indicates if the portstr received is src or dst
1147
 *                port.  For src port: flag = 0, dst port: flag = 1.
1148
 *
1149
 * \retval  0 On success.
1150
 * \retval -1 On failure.
1151
 */
1152
static int SigParsePort(const DetectEngineCtx *de_ctx,
1153
        Signature *s, const char *portstr, char flag)
1154
5.68M
{
1155
5.68M
    int r = 0;
1156
1157
    /* XXX VJ exclude handling this for none UDP/TCP proto's */
1158
1159
5.68M
    SCLogDebug("Port group \"%s\" to be parsed", portstr);
1160
1161
5.68M
    if (flag == 0) {
1162
2.85M
        if (strcasecmp(portstr, "any") == 0)
1163
2.26M
            s->flags |= SIG_FLAG_SP_ANY;
1164
1165
2.85M
        r = DetectPortParse(de_ctx, &s->sp, (char *)portstr);
1166
2.85M
    } else if (flag == 1) {
1167
2.82M
        if (strcasecmp(portstr, "any") == 0)
1168
2.03M
            s->flags |= SIG_FLAG_DP_ANY;
1169
1170
2.82M
        r = DetectPortParse(de_ctx, &s->dp, (char *)portstr);
1171
2.82M
    }
1172
1173
5.68M
    if (r < 0)
1174
129k
        return -1;
1175
1176
5.55M
    return 0;
1177
5.68M
}
1178
1179
/** \retval 1 valid
1180
 *  \retval 0 invalid
1181
 */
1182
static int SigParseActionRejectValidate(const char *action)
1183
691
{
1184
#ifdef HAVE_LIBNET11
1185
#if defined HAVE_LIBCAP_NG && !defined HAVE_LIBNET_CAPABILITIES
1186
    if (sc_set_caps == TRUE) {
1187
        SCLogError("Libnet 1.1 is "
1188
                   "incompatible with POSIX based capabilities with privs dropping. "
1189
                   "For rejects to work, run as root/super user.");
1190
        return 0;
1191
    }
1192
#endif
1193
#else /* no libnet 1.1 */
1194
691
    SCLogError("Libnet 1.1.x is "
1195
691
               "required for action \"%s\" but is not compiled into Suricata",
1196
691
            action);
1197
691
    return 0;
1198
0
#endif
1199
0
    return 1;
1200
691
}
1201
1202
/**
1203
 * \brief Parses the action that has been used by the Signature and allots it
1204
 *        to its Signature instance.
1205
 *
1206
 * \param s      Pointer to the Signature instance to which the action belongs.
1207
 * \param action Pointer to the action string used by the Signature.
1208
 *
1209
 * \retval  0 On successfully parsing the action string and adding it to the
1210
 *            Signature.
1211
 * \retval -1 On failure.
1212
 */
1213
static int SigParseAction(Signature *s, const char *action)
1214
1.95M
{
1215
1.95M
    if (strcasecmp(action, "alert") == 0) {
1216
1.62M
        s->action = ACTION_ALERT;
1217
1.62M
    } else if (strcasecmp(action, "drop") == 0) {
1218
73.2k
        s->action = ACTION_DROP | ACTION_ALERT;
1219
248k
    } else if (strcasecmp(action, "pass") == 0) {
1220
168k
        s->action = ACTION_PASS;
1221
168k
    } else if (strcasecmp(action, "reject") == 0 ||
1222
79.8k
               strcasecmp(action, "rejectsrc") == 0)
1223
85
    {
1224
85
        if (!(SigParseActionRejectValidate(action)))
1225
85
            return -1;
1226
0
        s->action = ACTION_REJECT | ACTION_DROP | ACTION_ALERT;
1227
79.8k
    } else if (strcasecmp(action, "rejectdst") == 0) {
1228
84
        if (!(SigParseActionRejectValidate(action)))
1229
84
            return -1;
1230
0
        s->action = ACTION_REJECT_DST | ACTION_DROP | ACTION_ALERT;
1231
79.7k
    } else if (strcasecmp(action, "rejectboth") == 0) {
1232
75
        if (!(SigParseActionRejectValidate(action)))
1233
75
            return -1;
1234
0
        s->action = ACTION_REJECT_BOTH | ACTION_DROP | ACTION_ALERT;
1235
79.6k
    } else if (strcasecmp(action, "config") == 0) {
1236
16.0k
        s->action = ACTION_CONFIG;
1237
63.6k
    } else {
1238
63.6k
        SCLogError("An invalid action \"%s\" was given", action);
1239
63.6k
        return -1;
1240
63.6k
    }
1241
1.88M
    return 0;
1242
1.95M
}
1243
1244
/**
1245
 * \brief Parse the next token in rule.
1246
 *
1247
 * For rule parsing a token is considered to be a string of characters
1248
 * separated by white space.
1249
 *
1250
 * \param input double pointer to input buffer, will be advanced as input is
1251
 *     parsed.
1252
 * \param output buffer to copy token into.
1253
 * \param output_size length of output buffer.
1254
 */
1255
static inline int SigParseToken(char **input, char *output,
1256
    const size_t output_size)
1257
19.0M
{
1258
19.0M
    size_t len = *input == NULL ? 0 : strlen(*input);
1259
1260
19.0M
    if (!len) {
1261
1.05M
        return 0;
1262
1.05M
    }
1263
1264
18.2M
    while (len && isblank(**input)) {
1265
243k
        (*input)++;
1266
243k
        len--;
1267
243k
    }
1268
1269
18.0M
    char *endptr = strpbrk(*input, " \t\n\r");
1270
18.0M
    if (endptr != NULL) {
1271
17.5M
        *(endptr++) = '\0';
1272
17.5M
    }
1273
18.0M
    strlcpy(output, *input, output_size);
1274
18.0M
    *input = endptr;
1275
1276
18.0M
    return 1;
1277
19.0M
}
1278
1279
/**
1280
 * \brief Parse the next rule "list" token.
1281
 *
1282
 * Parses rule tokens that may be lists such as addresses and ports
1283
 * handling the case when they may not be lists.
1284
 *
1285
 * \param input double pointer to input buffer, will be advanced as input is
1286
 *     parsed.
1287
 * \param output buffer to copy token into.
1288
 * \param output_size length of output buffer.
1289
 */
1290
static inline int SigParseList(char **input, char *output,
1291
    const size_t output_size)
1292
47.7M
{
1293
47.7M
    int in_list = 0;
1294
47.7M
    size_t len = *input != NULL ? strlen(*input) : 0;
1295
1296
47.7M
    if (len == 0) {
1297
4.51M
        return 0;
1298
4.51M
    }
1299
1300
44.1M
    while (len && isblank(**input)) {
1301
919k
        (*input)++;
1302
919k
        len--;
1303
919k
    }
1304
1305
43.1M
    size_t i = 0;
1306
245M
    for (i = 0; i < len; i++) {
1307
244M
        char c = (*input)[i];
1308
244M
        if (c == '[') {
1309
734k
            in_list++;
1310
244M
        } else if (c == ']') {
1311
822k
            in_list--;
1312
243M
        } else if (c == ' ') {
1313
43.1M
            if (!in_list) {
1314
42.3M
                break;
1315
42.3M
            }
1316
43.1M
        }
1317
244M
    }
1318
43.1M
    if (i == len) {
1319
880k
        *input = NULL;
1320
880k
        return 0;
1321
880k
    }
1322
42.3M
    (*input)[i] = '\0';
1323
42.3M
    strlcpy(output, *input, output_size);
1324
42.3M
    *input = *input + i + 1;
1325
1326
42.3M
    return 1;
1327
43.1M
}
1328
1329
/**
1330
 *  \internal
1331
 *  \brief split a signature string into a few blocks for further parsing
1332
 *
1333
 *  \param scan_only just scan, don't validate
1334
 */
1335
static int SigParseBasics(DetectEngineCtx *de_ctx, Signature *s, const char *sigstr,
1336
        SignatureParser *parser, uint8_t addrs_direction, bool scan_only)
1337
5.63M
{
1338
5.63M
    char *index, dup[DETECT_MAX_RULE_SIZE];
1339
1340
5.63M
    strlcpy(dup, sigstr, DETECT_MAX_RULE_SIZE);
1341
5.63M
    index = dup;
1342
1343
    /* Action. */
1344
5.63M
    SigParseToken(&index, parser->action, sizeof(parser->action));
1345
1346
    /* Protocol. */
1347
5.63M
    SigParseList(&index, parser->protocol, sizeof(parser->protocol));
1348
1349
    /* Source. */
1350
5.63M
    SigParseList(&index, parser->src, sizeof(parser->src));
1351
1352
    /* Source port(s). */
1353
5.63M
    SigParseList(&index, parser->sp, sizeof(parser->sp));
1354
1355
    /* Direction. */
1356
5.63M
    SigParseToken(&index, parser->direction, sizeof(parser->direction));
1357
1358
    /* Destination. */
1359
5.63M
    SigParseList(&index, parser->dst, sizeof(parser->dst));
1360
1361
    /* Destination port(s). */
1362
5.63M
    SigParseList(&index, parser->dp, sizeof(parser->dp));
1363
1364
    /* Options. */
1365
5.63M
    if (index == NULL) {
1366
842k
        SCLogError("no rule options.");
1367
842k
        goto error;
1368
842k
    }
1369
8.25M
    while (isspace(*index) || *index == '(') {
1370
3.46M
        index++;
1371
3.46M
    }
1372
9.35M
    for (size_t i = strlen(index); i > 0; i--) {
1373
9.24M
        if (isspace(index[i - 1]) || index[i - 1] == ')') {
1374
4.56M
            index[i - 1] = '\0';
1375
4.68M
        } else {
1376
4.68M
            break;
1377
4.68M
        }
1378
9.24M
    }
1379
4.78M
    strlcpy(parser->opts, index, sizeof(parser->opts));
1380
1381
4.78M
    if (scan_only) {
1382
2.83M
        return 0;
1383
2.83M
    }
1384
1385
    /* Parse Action */
1386
1.95M
    if (SigParseAction(s, parser->action) < 0)
1387
63.8k
        goto error;
1388
1389
1.88M
    if (SigParseProto(s, parser->protocol) < 0)
1390
53.1k
        goto error;
1391
1392
1.83M
    if (strcmp(parser->direction, "<>") == 0) {
1393
439k
        s->init_data->init_flags |= SIG_FLAG_INIT_BIDIREC;
1394
1.39M
    } else if (strcmp(parser->direction, "->") != 0) {
1395
74.9k
        SCLogError("\"%s\" is not a valid direction modifier, "
1396
74.9k
                   "\"->\" and \"<>\" are supported.",
1397
74.9k
                parser->direction);
1398
74.9k
        goto error;
1399
74.9k
    }
1400
1401
    /* Parse Address & Ports */
1402
1.75M
    if (SigParseAddress(de_ctx, s, parser->src, SIG_DIREC_SRC ^ addrs_direction) < 0)
1403
37.5k
       goto error;
1404
1405
1.72M
    if (SigParseAddress(de_ctx, s, parser->dst, SIG_DIREC_DST ^ addrs_direction) < 0)
1406
61.4k
        goto error;
1407
1408
    /* By AWS - Traditionally we should be doing this only for tcp/udp/sctp,
1409
     * but we do it for regardless of ip proto, since the dns/dnstcp/dnsudp
1410
     * changes that we made sees to it that at this point of time we don't
1411
     * set the ip proto for the sig.  We do it a bit later. */
1412
1.65M
    if (SigParsePort(de_ctx, s, parser->sp, SIG_DIREC_SRC ^ addrs_direction) < 0)
1413
14.3k
        goto error;
1414
1.64M
    if (SigParsePort(de_ctx, s, parser->dp, SIG_DIREC_DST ^ addrs_direction) < 0)
1415
59.4k
        goto error;
1416
1417
1.58M
    return 0;
1418
1419
1.20M
error:
1420
1.20M
    return -1;
1421
1.64M
}
1422
1423
static inline bool CheckAscii(const char *str)
1424
9.97M
{
1425
1.53G
    for (size_t i = 0; i < strlen(str); i++) {
1426
1.52G
        if (str[i] < 0x20) {
1427
            // LF CR TAB
1428
3.38M
            if (str[i] == 0x0a || str[i] == 0x0d || str[i] == 0x09) {
1429
2.98M
                continue;
1430
2.98M
            }
1431
401k
            return false;
1432
1.52G
        } else if (str[i] == 0x7f) {
1433
31.1k
            return false;
1434
31.1k
        }
1435
1.52G
    }
1436
9.54M
    return true;
1437
9.97M
}
1438
1439
/**
1440
 *  \brief parse a signature
1441
 *
1442
 *  \param de_ctx detection engine ctx to add it to
1443
 *  \param s memory structure to store the signature in
1444
 *  \param sigstr the raw signature as a null terminated string
1445
 *  \param addrs_direction direction (for bi-directional sigs)
1446
 *  \param require only scan rule for requires
1447
 *
1448
 *  \param -1 parse error
1449
 *  \param 0 ok
1450
 */
1451
static int SigParse(DetectEngineCtx *de_ctx, Signature *s, const char *sigstr,
1452
        uint8_t addrs_direction, SignatureParser *parser, bool requires)
1453
6.72M
{
1454
6.72M
    SCEnter();
1455
1456
6.72M
    if (!rs_check_utf8(sigstr)) {
1457
844k
        SCLogError("rule is not valid UTF-8");
1458
844k
        SCReturnInt(-1);
1459
844k
    }
1460
1461
5.88M
    if (!CheckAscii(sigstr)) {
1462
253k
        SCLogError("rule contains invalid (control) characters");
1463
253k
        SCReturnInt(-1);
1464
253k
    }
1465
1466
5.63M
    int ret = SigParseBasics(de_ctx, s, sigstr, parser, addrs_direction, requires);
1467
5.63M
    if (ret < 0) {
1468
1.20M
        SCLogDebug("SigParseBasics failed");
1469
1.20M
        SCReturnInt(-1);
1470
1.20M
    }
1471
1472
    /* we can have no options, so make sure we have them */
1473
4.42M
    if (strlen(parser->opts) > 0) {
1474
4.31M
        size_t buffer_size = strlen(parser->opts) + 1;
1475
4.31M
        char input[buffer_size];
1476
4.31M
        char output[buffer_size];
1477
4.31M
        memset(input, 0x00, buffer_size);
1478
4.31M
        memcpy(input, parser->opts, strlen(parser->opts) + 1);
1479
1480
        /* loop the option parsing. Each run processes one option
1481
         * and returns the rest of the option string through the
1482
         * output variable. */
1483
18.9M
        do {
1484
18.9M
            memset(output, 0x00, buffer_size);
1485
18.9M
            ret = SigParseOptions(de_ctx, s, input, output, buffer_size, requires);
1486
18.9M
            if (ret == 1) {
1487
14.5M
                memcpy(input, output, buffer_size);
1488
14.5M
            }
1489
1490
18.9M
        } while (ret == 1);
1491
1492
4.31M
        if (ret < 0) {
1493
            /* Suricata didn't meet the rule requirements, skip. */
1494
1.12M
            goto end;
1495
1.12M
        }
1496
4.31M
    }
1497
1498
4.42M
end:
1499
4.42M
    DetectIPProtoRemoveAllSMs(de_ctx, s);
1500
1501
4.42M
    SCReturnInt(ret);
1502
4.42M
}
1503
1504
/** \brief check if buffers array still has space left, expand if not
1505
 */
1506
int SignatureInitDataBufferCheckExpand(Signature *s)
1507
1.34M
{
1508
1.34M
    if (s->init_data->buffers_size >= 64)
1509
17
        return -1;
1510
1511
1.34M
    if (s->init_data->buffer_index + 1 == s->init_data->buffers_size) {
1512
4.65k
        void *ptr = SCRealloc(s->init_data->buffers,
1513
4.65k
                (s->init_data->buffers_size + 8) * sizeof(SignatureInitDataBuffer));
1514
4.65k
        if (ptr == NULL)
1515
0
            return -1;
1516
4.65k
        s->init_data->buffers = ptr;
1517
41.9k
        for (uint32_t x = s->init_data->buffers_size; x < s->init_data->buffers_size + 8; x++) {
1518
37.2k
            SignatureInitDataBuffer *b = &s->init_data->buffers[x];
1519
37.2k
            memset(b, 0, sizeof(*b));
1520
37.2k
        }
1521
4.65k
        s->init_data->buffers_size += 8;
1522
4.65k
    }
1523
1.34M
    return 0;
1524
1.34M
}
1525
1526
Signature *SigAlloc (void)
1527
7.99M
{
1528
7.99M
    Signature *sig = SCMalloc(sizeof(Signature));
1529
7.99M
    if (unlikely(sig == NULL))
1530
0
        return NULL;
1531
7.99M
    memset(sig, 0, sizeof(Signature));
1532
1533
7.99M
    sig->init_data = SCCalloc(1, sizeof(SignatureInitData));
1534
7.99M
    if (sig->init_data == NULL) {
1535
0
        SCFree(sig);
1536
0
        return NULL;
1537
0
    }
1538
7.99M
    sig->init_data->mpm_sm_list = -1;
1539
1540
7.99M
    sig->init_data->buffers = SCCalloc(8, sizeof(SignatureInitDataBuffer));
1541
7.99M
    if (sig->init_data->buffers == NULL) {
1542
0
        SCFree(sig->init_data);
1543
0
        SCFree(sig);
1544
0
        return NULL;
1545
0
    }
1546
7.99M
    sig->init_data->buffers_size = 8;
1547
1548
    /* assign it to -1, so that we can later check if the value has been
1549
     * overwritten after the Signature has been parsed, and if it hasn't been
1550
     * overwritten, we can then assign the default value of 3 */
1551
7.99M
    sig->prio = -1;
1552
1553
7.99M
    sig->init_data->list = DETECT_SM_LIST_NOTSET;
1554
7.99M
    return sig;
1555
7.99M
}
1556
1557
/**
1558
 * \internal
1559
 * \brief Free Metadata list
1560
 *
1561
 * \param s Pointer to the signature
1562
 */
1563
static void SigMetadataFree(Signature *s)
1564
7.99M
{
1565
7.99M
    SCEnter();
1566
1567
7.99M
    DetectMetadata *mdata = NULL;
1568
7.99M
    DetectMetadata *next_mdata = NULL;
1569
1570
7.99M
    if (s == NULL || s->metadata == NULL) {
1571
7.93M
        SCReturn;
1572
7.93M
    }
1573
1574
69.1k
    SCLogDebug("s %p, s->metadata %p", s, s->metadata);
1575
1576
238k
    for (mdata = s->metadata->list; mdata != NULL;)   {
1577
168k
        next_mdata = mdata->next;
1578
168k
        DetectMetadataFree(mdata);
1579
168k
        mdata = next_mdata;
1580
168k
    }
1581
69.1k
    SCFree(s->metadata->json_str);
1582
69.1k
    SCFree(s->metadata);
1583
69.1k
    s->metadata = NULL;
1584
1585
69.1k
    SCReturn;
1586
7.99M
}
1587
1588
/**
1589
 * \internal
1590
 * \brief Free Reference list
1591
 *
1592
 * \param s Pointer to the signature
1593
 */
1594
static void SigRefFree (Signature *s)
1595
7.99M
{
1596
7.99M
    SCEnter();
1597
1598
7.99M
    DetectReference *ref = NULL;
1599
7.99M
    DetectReference *next_ref = NULL;
1600
1601
7.99M
    if (s == NULL) {
1602
0
        SCReturn;
1603
0
    }
1604
1605
7.99M
    SCLogDebug("s %p, s->references %p", s, s->references);
1606
1607
8.25M
    for (ref = s->references; ref != NULL;)   {
1608
253k
        next_ref = ref->next;
1609
253k
        DetectReferenceFree(ref);
1610
253k
        ref = next_ref;
1611
253k
    }
1612
1613
7.99M
    s->references = NULL;
1614
1615
7.99M
    SCReturn;
1616
7.99M
}
1617
1618
static void SigMatchFreeArrays(DetectEngineCtx *de_ctx, Signature *s, int ctxs)
1619
7.99M
{
1620
7.99M
    if (s != NULL) {
1621
7.99M
        int type;
1622
63.9M
        for (type = 0; type < DETECT_SM_LIST_MAX; type++) {
1623
55.9M
            if (s->sm_arrays[type] != NULL) {
1624
168k
                if (ctxs) {
1625
168k
                    SigMatchData *smd = s->sm_arrays[type];
1626
296k
                    while(1) {
1627
296k
                        if (sigmatch_table[smd->type].Free != NULL) {
1628
292k
                            sigmatch_table[smd->type].Free(de_ctx, smd->ctx);
1629
292k
                        }
1630
296k
                        if (smd->is_last)
1631
168k
                            break;
1632
128k
                        smd++;
1633
128k
                    }
1634
168k
                }
1635
1636
168k
                SCFree(s->sm_arrays[type]);
1637
168k
            }
1638
55.9M
        }
1639
7.99M
    }
1640
7.99M
}
1641
1642
void SigFree(DetectEngineCtx *de_ctx, Signature *s)
1643
4.79M
{
1644
4.79M
    if (s == NULL)
1645
14.5k
        return;
1646
1647
4.77M
    if (s->cidr_dst != NULL)
1648
65.7k
        IPOnlyCIDRListFree(s->cidr_dst);
1649
1650
4.77M
    if (s->cidr_src != NULL)
1651
66.0k
        IPOnlyCIDRListFree(s->cidr_src);
1652
1653
4.77M
    int i;
1654
1655
4.77M
    if (s->init_data && s->init_data->transforms.cnt) {
1656
34.2k
        for(i = 0; i < s->init_data->transforms.cnt; i++) {
1657
19.3k
            if (s->init_data->transforms.transforms[i].options) {
1658
8.02k
                int transform = s->init_data->transforms.transforms[i].transform;
1659
8.02k
                sigmatch_table[transform].Free(
1660
8.02k
                        de_ctx, s->init_data->transforms.transforms[i].options);
1661
8.02k
                s->init_data->transforms.transforms[i].options = NULL;
1662
8.02k
            }
1663
19.3k
        }
1664
14.9k
    }
1665
4.77M
    if (s->init_data) {
1666
37.2M
        for (i = 0; i < DETECT_SM_LIST_MAX; i++) {
1667
32.5M
            SigMatch *sm = s->init_data->smlists[i];
1668
33.5M
            while (sm != NULL) {
1669
952k
                SigMatch *nsm = sm->next;
1670
952k
                SigMatchFree(de_ctx, sm);
1671
952k
                sm = nsm;
1672
952k
            }
1673
32.5M
        }
1674
1675
5.34M
        for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1676
693k
            SigMatch *sm = s->init_data->buffers[x].head;
1677
1.41M
            while (sm != NULL) {
1678
718k
                SigMatch *nsm = sm->next;
1679
718k
                SigMatchFree(de_ctx, sm);
1680
718k
                sm = nsm;
1681
718k
            }
1682
693k
        }
1683
4.65M
        SCFree(s->init_data->buffers);
1684
4.65M
        s->init_data->buffers = NULL;
1685
4.65M
    }
1686
4.77M
    SigMatchFreeArrays(de_ctx, s, (s->init_data == NULL));
1687
4.77M
    if (s->init_data) {
1688
4.65M
        SCFree(s->init_data);
1689
4.65M
        s->init_data = NULL;
1690
4.65M
    }
1691
1692
4.77M
    if (s->sp != NULL) {
1693
1.64M
        DetectPortCleanupList(NULL, s->sp);
1694
1.64M
    }
1695
4.77M
    if (s->dp != NULL) {
1696
1.58M
        DetectPortCleanupList(NULL, s->dp);
1697
1.58M
    }
1698
1699
4.77M
    if (s->msg != NULL)
1700
864k
        SCFree(s->msg);
1701
1702
4.77M
    if (s->addr_src_match4 != NULL) {
1703
735k
        SCFree(s->addr_src_match4);
1704
735k
    }
1705
4.77M
    if (s->addr_dst_match4 != NULL) {
1706
740k
        SCFree(s->addr_dst_match4);
1707
740k
    }
1708
4.77M
    if (s->addr_src_match6 != NULL) {
1709
803k
        SCFree(s->addr_src_match6);
1710
803k
    }
1711
4.77M
    if (s->addr_dst_match6 != NULL) {
1712
799k
        SCFree(s->addr_dst_match6);
1713
799k
    }
1714
4.77M
    if (s->sig_str != NULL) {
1715
4.77M
        SCFree(s->sig_str);
1716
4.77M
    }
1717
1718
4.77M
    SigRefFree(s);
1719
4.77M
    SigMetadataFree(s);
1720
1721
4.77M
    DetectEngineAppInspectionEngineSignatureFree(de_ctx, s);
1722
1723
4.77M
    SCFree(s);
1724
4.77M
}
1725
1726
int DetectSignatureAddTransform(Signature *s, int transform, void *options)
1727
110k
{
1728
    /* we only support buffers */
1729
110k
    if (s->init_data->list == 0) {
1730
0
        SCReturnInt(-1);
1731
0
    }
1732
110k
    if (!s->init_data->list_set) {
1733
1.64k
        SCLogError("transforms must directly follow stickybuffers");
1734
1.64k
        SCReturnInt(-1);
1735
1.64k
    }
1736
108k
    if (s->init_data->transforms.cnt >= DETECT_TRANSFORMS_MAX) {
1737
2
        SCReturnInt(-1);
1738
2
    }
1739
1740
108k
    s->init_data->transforms.transforms[s->init_data->transforms.cnt].transform = transform;
1741
108k
    s->init_data->transforms.transforms[s->init_data->transforms.cnt].options = options;
1742
1743
108k
    s->init_data->transforms.cnt++;
1744
108k
    SCLogDebug("Added transform #%d [%s]",
1745
108k
            s->init_data->transforms.cnt,
1746
108k
            s->sig_str);
1747
1748
108k
    SCReturnInt(0);
1749
108k
}
1750
1751
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
1752
696k
{
1753
696k
    if (alproto == ALPROTO_UNKNOWN ||
1754
696k
        alproto >= ALPROTO_FAILED) {
1755
0
        SCLogError("invalid alproto %u", alproto);
1756
0
        return -1;
1757
0
    }
1758
1759
    /* since AppProtoEquals is quite permissive wrt dcerpc and smb, make sure
1760
     * we refuse `alert dcerpc ... smb.share; content...` explicitly. */
1761
696k
    if (alproto == ALPROTO_SMB && s->alproto == ALPROTO_DCERPC) {
1762
0
        SCLogError("can't set rule app proto to %s: already set to %s", AppProtoToString(alproto),
1763
0
                AppProtoToString(s->alproto));
1764
0
        return -1;
1765
0
    }
1766
1767
696k
    if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, alproto)) {
1768
64.8k
        if (AppProtoEquals(alproto, s->alproto)) {
1769
            // happens if alproto = HTTP_ANY and s->alproto = HTTP1
1770
            // in this case, we must keep the most restrictive HTTP1
1771
42.7k
            alproto = s->alproto;
1772
42.7k
        } else {
1773
22.1k
            SCLogError("can't set rule app proto to %s: already set to %s",
1774
22.1k
                    AppProtoToString(alproto), AppProtoToString(s->alproto));
1775
22.1k
            return -1;
1776
22.1k
        }
1777
64.8k
    }
1778
1779
674k
    if (AppLayerProtoDetectGetProtoName(alproto) == NULL) {
1780
505
        SCLogError("disabled alproto %s, rule can never match", AppProtoToString(alproto));
1781
505
        return -1;
1782
505
    }
1783
674k
    s->alproto = alproto;
1784
674k
    s->flags |= SIG_FLAG_APPLAYER;
1785
674k
    return 0;
1786
674k
}
1787
1788
/**
1789
 *  \internal
1790
 *  \brief build address match array for cache efficient matching
1791
 *
1792
 *  \param s the signature
1793
 */
1794
static void SigBuildAddressMatchArray(Signature *s)
1795
814k
{
1796
    /* source addresses */
1797
814k
    uint16_t cnt = 0;
1798
814k
    uint16_t idx = 0;
1799
814k
    DetectAddress *da = s->init_data->src->ipv4_head;
1800
1.55M
    for ( ; da != NULL; da = da->next) {
1801
742k
        cnt++;
1802
742k
    }
1803
814k
    if (cnt > 0) {
1804
735k
        s->addr_src_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1805
735k
        if (s->addr_src_match4 == NULL) {
1806
0
            exit(EXIT_FAILURE);
1807
0
        }
1808
1809
1.47M
        for (da = s->init_data->src->ipv4_head; da != NULL; da = da->next) {
1810
742k
            s->addr_src_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1811
742k
            s->addr_src_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1812
742k
            idx++;
1813
742k
        }
1814
735k
        s->addr_src_match4_cnt = cnt;
1815
735k
    }
1816
1817
    /* destination addresses */
1818
814k
    cnt = 0;
1819
814k
    idx = 0;
1820
814k
    da = s->init_data->dst->ipv4_head;
1821
1.55M
    for ( ; da != NULL; da = da->next) {
1822
744k
        cnt++;
1823
744k
    }
1824
814k
    if (cnt > 0) {
1825
740k
        s->addr_dst_match4 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv4));
1826
740k
        if (s->addr_dst_match4 == NULL) {
1827
0
            exit(EXIT_FAILURE);
1828
0
        }
1829
1830
1.48M
        for (da = s->init_data->dst->ipv4_head; da != NULL; da = da->next) {
1831
744k
            s->addr_dst_match4[idx].ip = SCNtohl(da->ip.addr_data32[0]);
1832
744k
            s->addr_dst_match4[idx].ip2 = SCNtohl(da->ip2.addr_data32[0]);
1833
744k
            idx++;
1834
744k
        }
1835
740k
        s->addr_dst_match4_cnt = cnt;
1836
740k
    }
1837
1838
    /* source addresses IPv6 */
1839
814k
    cnt = 0;
1840
814k
    idx = 0;
1841
814k
    da = s->init_data->src->ipv6_head;
1842
1.65M
    for ( ; da != NULL; da = da->next) {
1843
843k
        cnt++;
1844
843k
    }
1845
814k
    if (cnt > 0) {
1846
803k
        s->addr_src_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1847
803k
        if (s->addr_src_match6 == NULL) {
1848
0
            exit(EXIT_FAILURE);
1849
0
        }
1850
1851
1.64M
        for (da = s->init_data->src->ipv6_head; da != NULL; da = da->next) {
1852
843k
            s->addr_src_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1853
843k
            s->addr_src_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1854
843k
            s->addr_src_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1855
843k
            s->addr_src_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1856
843k
            s->addr_src_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1857
843k
            s->addr_src_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1858
843k
            s->addr_src_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1859
843k
            s->addr_src_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1860
843k
            idx++;
1861
843k
        }
1862
803k
        s->addr_src_match6_cnt = cnt;
1863
803k
    }
1864
1865
    /* destination addresses IPv6 */
1866
814k
    cnt = 0;
1867
814k
    idx = 0;
1868
814k
    da = s->init_data->dst->ipv6_head;
1869
1.65M
    for ( ; da != NULL; da = da->next) {
1870
841k
        cnt++;
1871
841k
    }
1872
814k
    if (cnt > 0) {
1873
799k
        s->addr_dst_match6 = SCMalloc(cnt * sizeof(DetectMatchAddressIPv6));
1874
799k
        if (s->addr_dst_match6 == NULL) {
1875
0
            exit(EXIT_FAILURE);
1876
0
        }
1877
1878
1.64M
        for (da = s->init_data->dst->ipv6_head; da != NULL; da = da->next) {
1879
841k
            s->addr_dst_match6[idx].ip[0] = SCNtohl(da->ip.addr_data32[0]);
1880
841k
            s->addr_dst_match6[idx].ip[1] = SCNtohl(da->ip.addr_data32[1]);
1881
841k
            s->addr_dst_match6[idx].ip[2] = SCNtohl(da->ip.addr_data32[2]);
1882
841k
            s->addr_dst_match6[idx].ip[3] = SCNtohl(da->ip.addr_data32[3]);
1883
841k
            s->addr_dst_match6[idx].ip2[0] = SCNtohl(da->ip2.addr_data32[0]);
1884
841k
            s->addr_dst_match6[idx].ip2[1] = SCNtohl(da->ip2.addr_data32[1]);
1885
841k
            s->addr_dst_match6[idx].ip2[2] = SCNtohl(da->ip2.addr_data32[2]);
1886
841k
            s->addr_dst_match6[idx].ip2[3] = SCNtohl(da->ip2.addr_data32[3]);
1887
841k
            idx++;
1888
841k
        }
1889
799k
        s->addr_dst_match6_cnt = cnt;
1890
799k
    }
1891
814k
}
1892
1893
static int SigMatchListLen(SigMatch *sm)
1894
1.77M
{
1895
1.77M
    int len = 0;
1896
2.37M
    for (; sm != NULL; sm = sm->next)
1897
603k
        len++;
1898
1899
1.77M
    return len;
1900
1.77M
}
1901
1902
/** \brief convert SigMatch list to SigMatchData array
1903
 *  \note ownership of sm->ctx is transferred to smd->ctx
1904
 */
1905
SigMatchData* SigMatchList2DataArray(SigMatch *head)
1906
1.77M
{
1907
1.77M
    int len = SigMatchListLen(head);
1908
1.77M
    if (len == 0)
1909
1.45M
        return NULL;
1910
1911
321k
    SigMatchData *smd = (SigMatchData *)SCCalloc(len, sizeof(SigMatchData));
1912
321k
    if (smd == NULL) {
1913
0
        FatalError("initializing the detection engine failed");
1914
0
    }
1915
321k
    SigMatchData *out = smd;
1916
1917
    /* Copy sm type and Context into array */
1918
321k
    SigMatch *sm = head;
1919
925k
    for (; sm != NULL; sm = sm->next, smd++) {
1920
603k
        smd->type = sm->type;
1921
603k
        smd->ctx = sm->ctx;
1922
603k
        sm->ctx = NULL; // SigMatch no longer owns the ctx
1923
603k
        smd->is_last = (sm->next == NULL);
1924
603k
    }
1925
321k
    return out;
1926
321k
}
1927
1928
/**
1929
 *  \internal
1930
 *  \brief validate a just parsed signature for internal inconsistencies
1931
 *
1932
 *  \param s just parsed signature
1933
 *
1934
 *  \retval 0 invalid
1935
 *  \retval 1 valid
1936
 */
1937
static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
1938
814k
{
1939
814k
    SCEnter();
1940
1941
814k
    uint32_t sig_flags = 0;
1942
814k
    int nlists = 0;
1943
1.28M
    for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1944
473k
        nlists = MAX(nlists, (int)s->init_data->buffers[x].id);
1945
473k
    }
1946
814k
    nlists += (nlists > 0);
1947
814k
    SCLogDebug("nlists %d", nlists);
1948
1949
814k
    if (s->init_data->curbuf && s->init_data->curbuf->head == NULL) {
1950
928
        SCLogError("rule %u setup buffer %s but didn't add matches to it", s->id,
1951
928
                DetectEngineBufferTypeGetNameById(de_ctx, s->init_data->curbuf->id));
1952
928
        SCReturnInt(0);
1953
928
    }
1954
1955
814k
    bool has_frame = false;
1956
813k
    bool has_app = false;
1957
813k
    bool has_pkt = false;
1958
813k
    bool has_pmatch = false;
1959
1960
    /* run buffer type validation callbacks if any */
1961
813k
    if (s->init_data->smlists[DETECT_SM_LIST_PMATCH]) {
1962
181k
        if (!DetectContentPMATCHValidateCallback(s))
1963
1.24k
            SCReturnInt(0);
1964
1965
180k
        has_pmatch = true;
1966
180k
    }
1967
1968
812k
    struct BufferVsDir {
1969
812k
        int ts;
1970
812k
        int tc;
1971
812k
    } bufdir[nlists + 1];
1972
812k
    memset(&bufdir, 0, (nlists + 1) * sizeof(struct BufferVsDir));
1973
1974
1.26M
    for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1975
471k
        SignatureInitDataBuffer *b = &s->init_data->buffers[x];
1976
471k
        const DetectBufferType *bt = DetectEngineBufferTypeGetById(de_ctx, b->id);
1977
471k
        if (bt == NULL) {
1978
0
            DEBUG_VALIDATE_BUG_ON(1); // should be impossible
1979
0
            continue;
1980
0
        }
1981
471k
        SCLogDebug("x %u b->id %u name %s", x, b->id, bt->name);
1982
1.06M
        for (SigMatch *sm = b->head; sm != NULL; sm = sm->next) {
1983
591k
            SCLogDebug("sm %u %s", sm->type, sigmatch_table[sm->type].name);
1984
591k
        }
1985
1986
471k
        if (b->head == NULL) {
1987
134
            SCLogError("no matches in sticky buffer %s", bt->name);
1988
134
            SCReturnInt(0);
1989
134
        }
1990
1991
471k
        has_frame |= bt->frame;
1992
471k
        has_app |= (bt->frame == false && bt->packet == false);
1993
471k
        has_pkt |= bt->packet;
1994
1995
471k
        if ((s->flags & SIG_FLAG_REQUIRE_PACKET) && bt->packet == false) {
1996
1.93k
            SCLogError("Signature combines packet "
1997
1.93k
                       "specific matches (like dsize, flags, ttl) with stream / "
1998
1.93k
                       "state matching by matching on app layer proto (like using "
1999
1.93k
                       "http_* keywords).");
2000
1.93k
            SCReturnInt(0);
2001
1.93k
        }
2002
2003
469k
        const DetectEngineAppInspectionEngine *app = de_ctx->app_inspect_engines;
2004
164M
        for (; app != NULL; app = app->next) {
2005
163M
            if (app->sm_list == b->id &&
2006
1.58M
                    (AppProtoEquals(s->alproto, app->alproto) || s->alproto == 0)) {
2007
1.24M
                SCLogDebug("engine %s dir %d alproto %d",
2008
1.24M
                        DetectEngineBufferTypeGetNameById(de_ctx, app->sm_list), app->dir,
2009
1.24M
                        app->alproto);
2010
1.24M
                SCLogDebug("b->id %d nlists %d", b->id, nlists);
2011
1.24M
                bufdir[b->id].ts += (app->dir == 0);
2012
1.24M
                bufdir[b->id].tc += (app->dir == 1);
2013
1.24M
            }
2014
163M
        }
2015
2016
469k
        if (!DetectEngineBufferRunValidateCallback(de_ctx, b->id, s, &de_ctx->sigerror)) {
2017
8.24k
            SCReturnInt(0);
2018
8.24k
        }
2019
2020
461k
        if (!DetectBsizeValidateContentCallback(s, b)) {
2021
11.9k
            SCReturnInt(0);
2022
11.9k
        }
2023
461k
    }
2024
2025
789k
    int ts_excl = 0;
2026
789k
    int tc_excl = 0;
2027
789k
    int dir_amb = 0;
2028
29.7M
    for (int x = 0; x < nlists; x++) {
2029
28.9M
        if (bufdir[x].ts == 0 && bufdir[x].tc == 0)
2030
28.5M
            continue;
2031
386k
        ts_excl += (bufdir[x].ts > 0 && bufdir[x].tc == 0);
2032
386k
        tc_excl += (bufdir[x].ts == 0 && bufdir[x].tc > 0);
2033
386k
        dir_amb += (bufdir[x].ts > 0 && bufdir[x].tc > 0);
2034
2035
386k
        SCLogDebug("%s/%d: %d/%d", DetectEngineBufferTypeGetNameById(de_ctx, x), x, bufdir[x].ts,
2036
386k
                bufdir[x].tc);
2037
386k
    }
2038
789k
    if (ts_excl && tc_excl) {
2039
378
        SCLogError("rule %u mixes keywords with conflicting directions", s->id);
2040
378
        SCReturnInt(0);
2041
789k
    } else if (ts_excl) {
2042
217k
        SCLogDebug("%u: implied rule direction is toserver", s->id);
2043
217k
        if (DetectFlowSetupImplicit(s, SIG_FLAG_TOSERVER) < 0) {
2044
174
            SCLogError("rule %u mixes keywords with conflicting directions", s->id);
2045
174
            SCReturnInt(0);
2046
174
        }
2047
571k
    } else if (tc_excl) {
2048
35.9k
        SCLogDebug("%u: implied rule direction is toclient", s->id);
2049
35.9k
        if (DetectFlowSetupImplicit(s, SIG_FLAG_TOCLIENT) < 0) {
2050
2.09k
            SCLogError("rule %u mixes keywords with conflicting directions", s->id);
2051
2.09k
            SCReturnInt(0);
2052
2.09k
        }
2053
535k
    } else if (dir_amb) {
2054
97.8k
        SCLogDebug("%u: rule direction cannot be deduced from keywords", s->id);
2055
97.8k
    }
2056
2057
787k
    if ((s->flags & SIG_FLAG_REQUIRE_PACKET) &&
2058
88.6k
        (s->flags & SIG_FLAG_REQUIRE_STREAM)) {
2059
86
        SCLogError("can't mix packet keywords with "
2060
86
                   "tcp-stream or flow:only_stream.  Invalidating signature.");
2061
86
        SCReturnInt(0);
2062
86
    }
2063
2064
786k
    if ((sig_flags & (SIG_FLAG_TOCLIENT | SIG_FLAG_TOSERVER)) == (SIG_FLAG_TOCLIENT | SIG_FLAG_TOSERVER)) {
2065
0
        SCLogError("You seem to have mixed keywords "
2066
0
                   "that require inspection in both directions.  Atm we only "
2067
0
                   "support keywords in one direction within a rule.");
2068
0
        SCReturnInt(0);
2069
0
    }
2070
2071
786k
    if (has_pmatch && has_frame) {
2072
187
        SCLogError("can't mix pure content and frame inspection");
2073
187
        SCReturnInt(0);
2074
187
    }
2075
786k
    if (has_app && has_frame) {
2076
12
        SCLogError("can't mix app-layer buffer and frame inspection");
2077
12
        SCReturnInt(0);
2078
12
    }
2079
786k
    if (has_pkt && has_frame) {
2080
0
        SCLogError("can't mix pkt buffer and frame inspection");
2081
0
        SCReturnInt(0);
2082
0
    }
2083
2084
    /* TCP: corner cases:
2085
     * - pkt vs stream vs depth/offset
2086
     * - pkt vs stream vs stream_size
2087
     */
2088
786k
    if (s->proto.proto[IPPROTO_TCP / 8] & (1 << (IPPROTO_TCP % 8))) {
2089
745k
        if (s->init_data->smlists[DETECT_SM_LIST_PMATCH]) {
2090
171k
            if (!(s->flags & (SIG_FLAG_REQUIRE_PACKET | SIG_FLAG_REQUIRE_STREAM))) {
2091
136k
                s->flags |= SIG_FLAG_REQUIRE_STREAM;
2092
371k
                for (SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_PMATCH]; sm != NULL;
2093
247k
                        sm = sm->next) {
2094
247k
                    if (sm->type == DETECT_CONTENT &&
2095
110k
                            (((DetectContentData *)(sm->ctx))->flags &
2096
110k
                             (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET))) {
2097
12.9k
                        s->flags |= SIG_FLAG_REQUIRE_PACKET;
2098
12.9k
                        break;
2099
12.9k
                    }
2100
247k
                }
2101
                /* if stream_size is in use, also inspect packets */
2102
177k
                for (SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH]; sm != NULL;
2103
136k
                        sm = sm->next) {
2104
42.8k
                    if (sm->type == DETECT_STREAM_SIZE) {
2105
2.06k
                        s->flags |= SIG_FLAG_REQUIRE_PACKET;
2106
2.06k
                        break;
2107
2.06k
                    }
2108
42.8k
                }
2109
136k
            }
2110
171k
        }
2111
745k
    }
2112
#ifdef HAVE_LUA
2113
    DetectLuaPostSetup(s);
2114
#endif
2115
2116
786k
    if ((s->init_data->init_flags & SIG_FLAG_INIT_JA) && s->alproto != ALPROTO_UNKNOWN &&
2117
4.01k
            s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
2118
19
        SCLogError("Cannot have ja3/ja4 with protocol %s.", AppProtoToString(s->alproto));
2119
19
        SCReturnInt(0);
2120
19
    }
2121
786k
    if ((s->flags & SIG_FLAG_FILESTORE) || s->file_flags != 0 ||
2122
759k
        (s->init_data->init_flags & SIG_FLAG_INIT_FILEDATA)) {
2123
51.9k
        if (s->alproto != ALPROTO_UNKNOWN &&
2124
12.9k
                !AppLayerParserSupportsFiles(IPPROTO_TCP, s->alproto))
2125
501
        {
2126
501
            SCLogError("protocol %s doesn't "
2127
501
                       "support file matching",
2128
501
                    AppProtoToString(s->alproto));
2129
501
            SCReturnInt(0);
2130
501
        }
2131
51.4k
        if (s->alproto == ALPROTO_HTTP2 && (s->file_flags & FILE_SIG_NEED_FILENAME)) {
2132
261
            SCLogError("protocol HTTP2 doesn't support file name matching");
2133
261
            SCReturnInt(0);
2134
261
        }
2135
2136
51.1k
        if (s->alproto == ALPROTO_HTTP1 || s->alproto == ALPROTO_HTTP) {
2137
9.77k
            AppLayerHtpNeedFileInspection();
2138
9.77k
        }
2139
51.1k
    }
2140
2141
786k
    SCReturnInt(1);
2142
786k
}
2143
2144
/**
2145
 * \internal
2146
 * \brief Helper function for SigInit().
2147
 */
2148
static Signature *SigInitHelper(DetectEngineCtx *de_ctx, const char *sigstr,
2149
                                uint8_t dir)
2150
4.77M
{
2151
4.77M
    SignatureParser parser;
2152
4.77M
    memset(&parser, 0x00, sizeof(parser));
2153
2154
4.77M
    Signature *sig = SigAlloc();
2155
4.77M
    if (sig == NULL)
2156
0
        goto error;
2157
2158
4.77M
    sig->sig_str = SCStrdup(sigstr);
2159
4.77M
    if (unlikely(sig->sig_str == NULL)) {
2160
0
        goto error;
2161
0
    }
2162
2163
    /* default gid to 1 */
2164
4.77M
    sig->gid = 1;
2165
2166
    /* We do a first parse of the rule in a requires, or scan-only
2167
     * mode. Syntactic errors will be picked up here, but the only
2168
     * part of the rule that is validated completely is the "requires"
2169
     * keyword. */
2170
4.77M
    int ret = SigParse(de_ctx, sig, sigstr, dir, &parser, true);
2171
4.77M
    if (ret == -4) {
2172
        /* Rule requirements not met. */
2173
9.14k
        de_ctx->sigerror_silent = true;
2174
9.14k
        de_ctx->sigerror_ok = true;
2175
9.14k
        de_ctx->sigerror_requires = true;
2176
9.14k
        goto error;
2177
4.77M
    } else if (ret < 0) {
2178
2.28M
        goto error;
2179
2.28M
    }
2180
2181
    /* Check for a SID before continuuing. */
2182
2.48M
    if (sig->id == 0) {
2183
529k
        SCLogError("Signature missing required value \"sid\".");
2184
529k
        goto error;
2185
529k
    }
2186
2187
    /* Now completely parse the rule. */
2188
1.95M
    ret = SigParse(de_ctx, sig, sigstr, dir, &parser, false);
2189
1.95M
    BUG_ON(ret == -4);
2190
1.95M
    if (ret == -3) {
2191
10.2k
        de_ctx->sigerror_silent = true;
2192
10.2k
        de_ctx->sigerror_ok = true;
2193
10.2k
        goto error;
2194
1.94M
    } else if (ret == -2) {
2195
0
        de_ctx->sigerror_silent = true;
2196
0
        goto error;
2197
1.94M
    } else if (ret < 0) {
2198
1.12M
        goto error;
2199
1.12M
    }
2200
2201
    /* signature priority hasn't been overwritten.  Using default priority */
2202
814k
    if (sig->prio == -1)
2203
678k
        sig->prio = DETECT_DEFAULT_PRIO;
2204
2205
814k
    sig->num = de_ctx->signum;
2206
814k
    de_ctx->signum++;
2207
2208
814k
    if (sig->alproto != ALPROTO_UNKNOWN) {
2209
475k
        int override_needed = 0;
2210
475k
        if (sig->proto.flags & DETECT_PROTO_ANY) {
2211
79.4k
            sig->proto.flags &= ~DETECT_PROTO_ANY;
2212
79.4k
            memset(sig->proto.proto, 0x00, sizeof(sig->proto.proto));
2213
79.4k
            override_needed = 1;
2214
396k
        } else {
2215
396k
            override_needed = 1;
2216
396k
            size_t s = 0;
2217
449k
            for (s = 0; s < sizeof(sig->proto.proto); s++) {
2218
449k
                if (sig->proto.proto[s] != 0x00) {
2219
396k
                    override_needed = 0;
2220
396k
                    break;
2221
396k
                }
2222
449k
            }
2223
396k
        }
2224
2225
        /* at this point if we had alert ip and the ip proto was not
2226
         * overridden, we use the ip proto that has been configured
2227
         * against the app proto in use. */
2228
475k
        if (override_needed)
2229
79.4k
            AppLayerProtoDetectSupportedIpprotos(sig->alproto, sig->proto.proto);
2230
475k
    }
2231
2232
    /* set the packet and app layer flags, but only if the
2233
     * app layer flag wasn't already set in which case we
2234
     * only consider the app layer */
2235
814k
    if (!(sig->flags & SIG_FLAG_APPLAYER)) {
2236
335k
        if (sig->init_data->smlists[DETECT_SM_LIST_MATCH] != NULL) {
2237
137k
            SigMatch *sm = sig->init_data->smlists[DETECT_SM_LIST_MATCH];
2238
342k
            for ( ; sm != NULL; sm = sm->next) {
2239
204k
                if (sigmatch_table[sm->type].Match != NULL)
2240
204k
                    sig->init_data->init_flags |= SIG_FLAG_INIT_PACKET;
2241
204k
            }
2242
198k
        } else {
2243
198k
            sig->init_data->init_flags |= SIG_FLAG_INIT_PACKET;
2244
198k
        }
2245
335k
    }
2246
2247
814k
    if (!(sig->init_data->init_flags & SIG_FLAG_INIT_FLOW)) {
2248
727k
        if ((sig->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) {
2249
705k
            sig->flags |= SIG_FLAG_TOSERVER;
2250
705k
            sig->flags |= SIG_FLAG_TOCLIENT;
2251
705k
        }
2252
727k
    }
2253
2254
814k
    SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
2255
814k
        sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
2256
814k
        sig->init_data->init_flags & SIG_FLAG_INIT_PACKET ? "set" : "not set");
2257
2258
814k
    SigBuildAddressMatchArray(sig);
2259
2260
    /* run buffer type callbacks if any */
2261
6.51M
    for (uint32_t x = 0; x < DETECT_SM_LIST_MAX; x++) {
2262
5.69M
        if (sig->init_data->smlists[x])
2263
470k
            DetectEngineBufferRunSetupCallback(de_ctx, x, sig);
2264
5.69M
    }
2265
1.28M
    for (uint32_t x = 0; x < sig->init_data->buffer_index; x++) {
2266
473k
        DetectEngineBufferRunSetupCallback(de_ctx, sig->init_data->buffers[x].id, sig);
2267
473k
    }
2268
2269
    /* validate signature, SigValidate will report the error reason */
2270
814k
    if (SigValidate(de_ctx, sig) == 0) {
2271
28.1k
        goto error;
2272
28.1k
    }
2273
2274
    /* check what the type of this sig is */
2275
786k
    SignatureSetType(de_ctx, sig);
2276
2277
786k
    if (sig->type == SIG_TYPE_IPONLY) {
2278
        /* For IPOnly */
2279
74.6k
        if (IPOnlySigParseAddress(de_ctx, sig, parser.src, SIG_DIREC_SRC ^ dir) < 0)
2280
608
            goto error;
2281
2282
74.0k
        if (IPOnlySigParseAddress(de_ctx, sig, parser.dst, SIG_DIREC_DST ^ dir) < 0)
2283
309
            goto error;
2284
74.0k
    }
2285
785k
    return sig;
2286
2287
3.99M
error:
2288
3.99M
    if (sig != NULL) {
2289
3.99M
        SigFree(de_ctx, sig);
2290
3.99M
    }
2291
3.99M
    return NULL;
2292
786k
}
2293
2294
/**
2295
 * \brief Checks if a signature has the same source and destination
2296
 * \param s parsed signature
2297
 *
2298
 *  \retval true if source and destination are the same, false otherwise
2299
 */
2300
static bool SigHasSameSourceAndDestination(const Signature *s)
2301
239k
{
2302
239k
    if (!(s->flags & SIG_FLAG_SP_ANY) || !(s->flags & SIG_FLAG_DP_ANY)) {
2303
224k
        if (!DetectPortListsAreEqual(s->sp, s->dp)) {
2304
217k
            return false;
2305
217k
        }
2306
224k
    }
2307
2308
21.9k
    if (!(s->flags & SIG_FLAG_SRC_ANY) || !(s->flags & SIG_FLAG_DST_ANY)) {
2309
21.5k
        DetectAddress *src = s->init_data->src->ipv4_head;
2310
21.5k
        DetectAddress *dst = s->init_data->dst->ipv4_head;
2311
2312
21.5k
        if (!DetectAddressListsAreEqual(src, dst)) {
2313
11.4k
            return false;
2314
11.4k
        }
2315
2316
10.0k
        src = s->init_data->src->ipv6_head;
2317
10.0k
        dst = s->init_data->dst->ipv6_head;
2318
2319
10.0k
        if (!DetectAddressListsAreEqual(src, dst)) {
2320
5.27k
            return false;
2321
5.27k
        }
2322
10.0k
    }
2323
2324
5.21k
    return true;
2325
21.9k
}
2326
2327
/**
2328
 * \brief Parses a signature and adds it to the Detection Engine Context.
2329
 *
2330
 * \param de_ctx Pointer to the Detection Engine Context.
2331
 * \param sigstr Pointer to a character string containing the signature to be
2332
 *               parsed.
2333
 *
2334
 * \retval Pointer to the Signature instance on success; NULL on failure.
2335
 */
2336
Signature *SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
2337
4.64M
{
2338
4.64M
    SCEnter();
2339
2340
4.64M
    uint32_t oldsignum = de_ctx->signum;
2341
4.64M
    de_ctx->sigerror_ok = false;
2342
4.64M
    de_ctx->sigerror_silent = false;
2343
4.64M
    de_ctx->sigerror_requires = false;
2344
2345
4.64M
    Signature *sig;
2346
2347
4.64M
    if ((sig = SigInitHelper(de_ctx, sigstr, SIG_DIREC_NORMAL)) == NULL) {
2348
3.99M
        goto error;
2349
3.99M
    }
2350
2351
649k
    if (sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2352
138k
        if (SigHasSameSourceAndDestination(sig)) {
2353
2.70k
            SCLogInfo("Rule with ID %u is bidirectional, but source and destination are the same, "
2354
2.70k
                "treating the rule as unidirectional", sig->id);
2355
2356
2.70k
            sig->init_data->init_flags &= ~SIG_FLAG_INIT_BIDIREC;
2357
135k
        } else {
2358
135k
            sig->next = SigInitHelper(de_ctx, sigstr, SIG_DIREC_SWITCHED);
2359
135k
            if (sig->next == NULL) {
2360
0
                goto error;
2361
0
            }
2362
135k
        }
2363
138k
    }
2364
2365
649k
    SCReturnPtr(sig, "Signature");
2366
2367
3.99M
error:
2368
3.99M
    if (sig != NULL) {
2369
0
        SigFree(de_ctx, sig);
2370
0
    }
2371
    /* if something failed, restore the old signum count
2372
     * since we didn't install it */
2373
3.99M
    de_ctx->signum = oldsignum;
2374
2375
3.99M
    SCReturnPtr(NULL, "Signature");
2376
649k
}
2377
2378
/**
2379
 * \brief The hash free function to be the used by the hash table -
2380
 *        DetectEngineCtx->dup_sig_hash_table.
2381
 *
2382
 * \param data    Pointer to the data, in our case SigDuplWrapper to be freed.
2383
 */
2384
static void DetectParseDupSigFreeFunc(void *data)
2385
107k
{
2386
107k
    if (data != NULL)
2387
107k
        SCFree(data);
2388
2389
107k
    return;
2390
107k
}
2391
2392
/**
2393
 * \brief The hash function to be the used by the hash table -
2394
 *        DetectEngineCtx->dup_sig_hash_table.
2395
 *
2396
 * \param ht      Pointer to the hash table.
2397
 * \param data    Pointer to the data, in our case SigDuplWrapper.
2398
 * \param datalen Not used in our case.
2399
 *
2400
 * \retval sw->s->id The generated hash value.
2401
 */
2402
static uint32_t DetectParseDupSigHashFunc(HashListTable *ht, void *data, uint16_t datalen)
2403
1.46M
{
2404
1.46M
    SigDuplWrapper *sw = (SigDuplWrapper *)data;
2405
2406
1.46M
    return (sw->s->id % ht->array_size);
2407
1.46M
}
2408
2409
/**
2410
 * \brief The Compare function to be used by the  hash table -
2411
 *        DetectEngineCtx->dup_sig_hash_table.
2412
 *
2413
 * \param data1 Pointer to the first SigDuplWrapper.
2414
 * \param len1  Not used.
2415
 * \param data2 Pointer to the second SigDuplWrapper.
2416
 * \param len2  Not used.
2417
 *
2418
 * \retval 1 If the 2 SigDuplWrappers sent as args match.
2419
 * \retval 0 If the 2 SigDuplWrappers sent as args do not match.
2420
 */
2421
static char DetectParseDupSigCompareFunc(void *data1, uint16_t len1, void *data2,
2422
                                  uint16_t len2)
2423
1.06M
{
2424
1.06M
    SigDuplWrapper *sw1 = (SigDuplWrapper *)data1;
2425
1.06M
    SigDuplWrapper *sw2 = (SigDuplWrapper *)data2;
2426
2427
1.06M
    if (sw1 == NULL || sw2 == NULL ||
2428
1.06M
        sw1->s == NULL || sw2->s == NULL)
2429
0
        return 0;
2430
2431
    /* sid and gid match required */
2432
1.06M
    if (sw1->s->id == sw2->s->id && sw1->s->gid == sw2->s->gid) return 1;
2433
2434
18.1k
    return 0;
2435
1.06M
}
2436
2437
/**
2438
 * \brief Initializes the hash table that is used to cull duplicate sigs.
2439
 *
2440
 * \param de_ctx Pointer to the detection engine context.
2441
 *
2442
 * \retval  0 On success.
2443
 * \retval -1 On failure.
2444
 */
2445
int DetectParseDupSigHashInit(DetectEngineCtx *de_ctx)
2446
156k
{
2447
156k
    de_ctx->dup_sig_hash_table = HashListTableInit(15000,
2448
156k
                                                   DetectParseDupSigHashFunc,
2449
156k
                                                   DetectParseDupSigCompareFunc,
2450
156k
                                                   DetectParseDupSigFreeFunc);
2451
156k
    if (de_ctx->dup_sig_hash_table == NULL)
2452
0
        return -1;
2453
2454
156k
    return 0;
2455
156k
}
2456
2457
/**
2458
 * \brief Frees the hash table that is used to cull duplicate sigs.
2459
 *
2460
 * \param de_ctx Pointer to the detection engine context that holds this table.
2461
 */
2462
void DetectParseDupSigHashFree(DetectEngineCtx *de_ctx)
2463
128k
{
2464
128k
    if (de_ctx->dup_sig_hash_table != NULL)
2465
64.3k
        HashListTableFree(de_ctx->dup_sig_hash_table);
2466
2467
128k
    de_ctx->dup_sig_hash_table = NULL;
2468
2469
128k
    return;
2470
128k
}
2471
2472
/**
2473
 * \brief Check if a signature is a duplicate.
2474
 *
2475
 *        There are 3 types of return values for this function.
2476
 *
2477
 *        - 0, which indicates that the Signature is not a duplicate
2478
 *          and has to be added to the detection engine list.
2479
 *        - 1, Signature is duplicate, and the existing signature in
2480
 *          the list shouldn't be replaced with this duplicate.
2481
 *        - 2, Signature is duplicate, and the existing signature in
2482
 *          the list should be replaced with this duplicate.
2483
 *
2484
 * \param de_ctx Pointer to the detection engine context.
2485
 * \param sig    Pointer to the Signature that has to be checked.
2486
 *
2487
 * \retval 2 If Signature is duplicate and the existing signature in
2488
 *           the list should be chucked out and replaced with this.
2489
 * \retval 1 If Signature is duplicate, and should be chucked out.
2490
 * \retval 0 If Signature is not a duplicate.
2491
 */
2492
static inline int DetectEngineSignatureIsDuplicate(DetectEngineCtx *de_ctx,
2493
                                                   Signature *sig)
2494
634k
{
2495
    /* we won't do any NULL checks on the args */
2496
2497
    /* return value */
2498
634k
    int ret = 0;
2499
2500
634k
    SigDuplWrapper *sw_dup = NULL;
2501
634k
    SigDuplWrapper *sw = NULL;
2502
2503
    /* used for making a duplicate_sig_hash_table entry */
2504
634k
    sw = SCMalloc(sizeof(SigDuplWrapper));
2505
634k
    if (unlikely(sw == NULL)) {
2506
0
        exit(EXIT_FAILURE);
2507
0
    }
2508
634k
    memset(sw, 0, sizeof(SigDuplWrapper));
2509
634k
    sw->s = sig;
2510
2511
    /* check if we have a duplicate entry for this signature */
2512
634k
    sw_dup = HashListTableLookup(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2513
    /* we don't have a duplicate entry for this sig */
2514
634k
    if (sw_dup == NULL) {
2515
        /* add it to the hash table */
2516
107k
        HashListTableAdd(de_ctx->dup_sig_hash_table, (void *)sw, 0);
2517
2518
        /* add the s_prev entry for the previously loaded sw in the hash_table */
2519
107k
        if (de_ctx->sig_list != NULL) {
2520
80.5k
            SigDuplWrapper *sw_old = NULL;
2521
80.5k
            SigDuplWrapper sw_tmp;
2522
80.5k
            memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2523
2524
            /* the topmost sig would be the last loaded sig */
2525
80.5k
            sw_tmp.s = de_ctx->sig_list;
2526
80.5k
            sw_old = HashListTableLookup(de_ctx->dup_sig_hash_table,
2527
80.5k
                                         (void *)&sw_tmp, 0);
2528
            /* sw_old == NULL case is impossible */
2529
80.5k
            sw_old->s_prev = sig;
2530
80.5k
        }
2531
2532
107k
        ret = 0;
2533
107k
        goto end;
2534
107k
    }
2535
2536
    /* if we have reached here we have a duplicate entry for this signature.
2537
     * Check the signature revision.  Store the signature with the latest rev
2538
     * and discard the other one */
2539
527k
    if (sw->s->rev <= sw_dup->s->rev) {
2540
526k
        ret = 1;
2541
526k
        SCFree(sw);
2542
526k
        sw = NULL;
2543
526k
        goto end;
2544
526k
    }
2545
2546
    /* the new sig is of a newer revision than the one that is already in the
2547
     * list.  Remove the old sig from the list */
2548
1.02k
    if (sw_dup->s_prev == NULL) {
2549
139
        SigDuplWrapper sw_temp;
2550
139
        memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2551
139
        if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2552
22
            sw_temp.s = sw_dup->s->next->next;
2553
22
            de_ctx->sig_list = sw_dup->s->next->next;
2554
22
            SigFree(de_ctx, sw_dup->s->next);
2555
117
        } else {
2556
117
            sw_temp.s = sw_dup->s->next;
2557
117
            de_ctx->sig_list = sw_dup->s->next;
2558
117
        }
2559
139
        SigDuplWrapper *sw_next = NULL;
2560
139
        if (sw_temp.s != NULL) {
2561
109
            sw_next = HashListTableLookup(de_ctx->dup_sig_hash_table,
2562
109
                                          (void *)&sw_temp, 0);
2563
109
            sw_next->s_prev = sw_dup->s_prev;
2564
109
        }
2565
139
        SigFree(de_ctx, sw_dup->s);
2566
883
    } else {
2567
883
        SigDuplWrapper sw_temp;
2568
883
        memset(&sw_temp, 0, sizeof(SigDuplWrapper));
2569
883
        if (sw_dup->s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2570
262
            sw_temp.s = sw_dup->s->next->next;
2571
            /* If previous signature is bidirectional,
2572
             * it has 2 items in the linked list.
2573
             * So we need to change next->next instead of next
2574
             */
2575
262
            if (sw_dup->s_prev->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2576
130
                sw_dup->s_prev->next->next = sw_dup->s->next->next;
2577
132
            } else {
2578
132
                sw_dup->s_prev->next = sw_dup->s->next->next;
2579
132
            }
2580
262
            SigFree(de_ctx, sw_dup->s->next);
2581
621
        } else {
2582
621
            sw_temp.s = sw_dup->s->next;
2583
621
            if (sw_dup->s_prev->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2584
150
                sw_dup->s_prev->next->next = sw_dup->s->next;
2585
471
            } else {
2586
471
                sw_dup->s_prev->next = sw_dup->s->next;
2587
471
            }
2588
621
        }
2589
883
        SigDuplWrapper *sw_next = NULL;
2590
883
        if (sw_temp.s != NULL) {
2591
718
            sw_next = HashListTableLookup(de_ctx->dup_sig_hash_table,
2592
718
                                          (void *)&sw_temp, 0);
2593
718
            sw_next->s_prev = sw_dup->s_prev;
2594
718
        }
2595
883
        SigFree(de_ctx, sw_dup->s);
2596
883
    }
2597
2598
    /* make changes to the entry to reflect the presence of the new sig */
2599
1.02k
    sw_dup->s = sig;
2600
1.02k
    sw_dup->s_prev = NULL;
2601
2602
1.02k
    if (de_ctx->sig_list != NULL) {
2603
992
        SigDuplWrapper sw_tmp;
2604
992
        memset(&sw_tmp, 0, sizeof(SigDuplWrapper));
2605
992
        sw_tmp.s = de_ctx->sig_list;
2606
992
        SigDuplWrapper *sw_old = HashListTableLookup(de_ctx->dup_sig_hash_table,
2607
992
                                                     (void *)&sw_tmp, 0);
2608
992
        if (sw_old->s != sw_dup->s) {
2609
            // Link on top of the list if there was another element
2610
992
            sw_old->s_prev = sig;
2611
992
        }
2612
992
    }
2613
2614
    /* this is duplicate, but a duplicate that replaced the existing sig entry */
2615
1.02k
    ret = 2;
2616
2617
1.02k
    SCFree(sw);
2618
2619
634k
end:
2620
634k
    return ret;
2621
1.02k
}
2622
2623
/**
2624
 * \brief Parse and append a Signature into the Detection Engine Context
2625
 *        signature list.
2626
 *
2627
 *        If the signature is bidirectional it should append two signatures
2628
 *        (with the addresses switched) into the list.  Also handle duplicate
2629
 *        signatures.  In case of duplicate sigs, use the ones that have the
2630
 *        latest revision.  We use the sid and the msg to identify duplicate
2631
 *        sigs.  If 2 sigs have the same sid and gid, they are duplicates.
2632
 *
2633
 * \param de_ctx Pointer to the Detection Engine Context.
2634
 * \param sigstr Pointer to a character string containing the signature to be
2635
 *               parsed.
2636
 * \param sig_file Pointer to a character string containing the filename from
2637
 *                 which signature is read
2638
 * \param lineno Line number from where signature is read
2639
 *
2640
 * \retval Pointer to the head Signature in the detection engine ctx sig_list
2641
 *         on success; NULL on failure.
2642
 */
2643
Signature *DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
2644
7.73M
{
2645
7.73M
    Signature *sig = SigInit(de_ctx, sigstr);
2646
7.73M
    if (sig == NULL) {
2647
6.61M
        return NULL;
2648
6.61M
    }
2649
2650
    /* checking for the status of duplicate signature */
2651
1.11M
    int dup_sig = DetectEngineSignatureIsDuplicate(de_ctx, sig);
2652
    /* a duplicate signature that should be chucked out.  Check the previously
2653
     * called function details to understand the different return values */
2654
1.11M
    if (dup_sig == 1) {
2655
908k
        SCLogError("Duplicate signature \"%s\"", sigstr);
2656
908k
        goto error;
2657
908k
    } else if (dup_sig == 2) {
2658
1.72k
        SCLogWarning("Signature with newer revision,"
2659
1.72k
                     " so the older sig replaced by this new signature \"%s\"",
2660
1.72k
                sigstr);
2661
1.72k
    }
2662
2663
210k
    if (sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC) {
2664
37.3k
        if (sig->next != NULL) {
2665
37.3k
            sig->next->next = de_ctx->sig_list;
2666
37.3k
        } else {
2667
0
            goto error;
2668
0
        }
2669
173k
    } else {
2670
        /* if this sig is the first one, sig_list should be null */
2671
173k
        sig->next = de_ctx->sig_list;
2672
173k
    }
2673
2674
210k
    de_ctx->sig_list = sig;
2675
2676
    /**
2677
     * In DetectEngineAppendSig(), the signatures are prepended and we always return the first one
2678
     * so if the signature is bidirectional, the returned sig will point through "next" ptr
2679
     * to the cloned signatures with the switched addresses
2680
     */
2681
210k
    return (dup_sig == 0 || dup_sig == 2) ? sig : NULL;
2682
2683
908k
error:
2684
    /* free the 2nd sig bidir may have set up */
2685
908k
    if (sig != NULL && sig->next != NULL) {
2686
185k
        SigFree(de_ctx, sig->next);
2687
185k
        sig->next = NULL;
2688
185k
    }
2689
908k
    if (sig != NULL) {
2690
908k
        SigFree(de_ctx, sig);
2691
908k
    }
2692
908k
    return NULL;
2693
210k
}
2694
2695
static DetectParseRegex *g_detect_parse_regex_list = NULL;
2696
2697
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str,
2698
        int start_offset, int options)
2699
2.25M
{
2700
2.25M
    *match = pcre2_match_data_create_from_pattern(parse_regex->regex, NULL);
2701
2.25M
    if (*match)
2702
2.25M
        return pcre2_match(parse_regex->regex, (PCRE2_SPTR8)str, strlen(str), options, start_offset,
2703
2.25M
                *match, parse_regex->context);
2704
0
    return -1;
2705
2.25M
}
2706
2707
void DetectParseFreeRegex(DetectParseRegex *r)
2708
390k
{
2709
390k
    if (r->regex) {
2710
327k
        pcre2_code_free(r->regex);
2711
327k
    }
2712
390k
    if (r->context) {
2713
327k
        pcre2_match_context_free(r->context);
2714
327k
    }
2715
390k
    if (r->match) {
2716
327k
        pcre2_match_data_free(r->match);
2717
327k
    }
2718
390k
}
2719
2720
void DetectParseFreeRegexes(void)
2721
0
{
2722
0
    DetectParseRegex *r = g_detect_parse_regex_list;
2723
0
    while (r) {
2724
0
        DetectParseRegex *next = r->next;
2725
2726
0
        DetectParseFreeRegex(r);
2727
2728
0
        SCFree(r);
2729
0
        r = next;
2730
0
    }
2731
0
    g_detect_parse_regex_list = NULL;
2732
0
}
2733
2734
/** \brief add regex and/or study to at exit free list
2735
 */
2736
void DetectParseRegexAddToFreeList(DetectParseRegex *detect_parse)
2737
3.29k
{
2738
3.29k
    DetectParseRegex *r = SCCalloc(1, sizeof(*r));
2739
3.29k
    if (r == NULL) {
2740
0
        FatalError("failed to alloc memory for pcre free list");
2741
0
    }
2742
3.29k
    r->regex = detect_parse->regex;
2743
3.29k
    r->match = detect_parse->match;
2744
3.29k
    r->next = g_detect_parse_regex_list;
2745
3.29k
    g_detect_parse_regex_list = r;
2746
3.29k
}
2747
2748
bool DetectSetupParseRegexesOpts(const char *parse_str, DetectParseRegex *detect_parse, int opts)
2749
3.29k
{
2750
3.29k
    int en;
2751
3.29k
    PCRE2_SIZE eo;
2752
2753
3.29k
    detect_parse->regex =
2754
3.29k
            pcre2_compile((PCRE2_SPTR8)parse_str, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
2755
3.29k
    if (detect_parse->regex == NULL) {
2756
0
        PCRE2_UCHAR errbuffer[256];
2757
0
        pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
2758
0
        SCLogError("pcre compile of \"%s\" failed at "
2759
0
                   "offset %d: %s",
2760
0
                parse_str, en, errbuffer);
2761
0
        return false;
2762
0
    }
2763
2764
3.29k
    detect_parse->context = pcre2_match_context_create(NULL);
2765
3.29k
    if (detect_parse->context == NULL) {
2766
0
        SCLogError("pcre2 could not create match context");
2767
0
        pcre2_code_free(detect_parse->regex);
2768
0
        detect_parse->regex = NULL;
2769
0
        return false;
2770
0
    }
2771
3.29k
    pcre2_set_match_limit(detect_parse->context, SC_MATCH_LIMIT_DEFAULT);
2772
3.29k
    pcre2_set_recursion_limit(detect_parse->context, SC_MATCH_LIMIT_RECURSION_DEFAULT);
2773
3.29k
    DetectParseRegexAddToFreeList(detect_parse);
2774
2775
3.29k
    return true;
2776
3.29k
}
2777
2778
DetectParseRegex *DetectSetupPCRE2(const char *parse_str, int opts)
2779
432
{
2780
432
    int en;
2781
432
    PCRE2_SIZE eo;
2782
432
    DetectParseRegex *detect_parse = SCCalloc(1, sizeof(DetectParseRegex));
2783
432
    if (detect_parse == NULL) {
2784
0
        return NULL;
2785
0
    }
2786
2787
432
    detect_parse->regex =
2788
432
            pcre2_compile((PCRE2_SPTR8)parse_str, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL);
2789
432
    if (detect_parse->regex == NULL) {
2790
0
        PCRE2_UCHAR errbuffer[256];
2791
0
        pcre2_get_error_message(en, errbuffer, sizeof(errbuffer));
2792
0
        SCLogError("pcre2 compile of \"%s\" failed at "
2793
0
                   "offset %d: %s",
2794
0
                parse_str, (int)eo, errbuffer);
2795
0
        SCFree(detect_parse);
2796
0
        return NULL;
2797
0
    }
2798
432
    detect_parse->match = pcre2_match_data_create_from_pattern(detect_parse->regex, NULL);
2799
2800
432
    detect_parse->next = g_detect_parse_regex_list;
2801
432
    g_detect_parse_regex_list = detect_parse;
2802
432
    return detect_parse;
2803
432
}
2804
2805
int SC_Pcre2SubstringCopy(
2806
        pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen)
2807
534k
{
2808
534k
    int r = pcre2_substring_copy_bynumber(match_data, number, buffer, bufflen);
2809
534k
    if (r == PCRE2_ERROR_UNSET) {
2810
89.3k
        buffer[0] = 0;
2811
89.3k
        *bufflen = 0;
2812
89.3k
        return 0;
2813
89.3k
    }
2814
445k
    return r;
2815
534k
}
2816
2817
int SC_Pcre2SubstringGet(
2818
        pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen)
2819
63.9k
{
2820
63.9k
    int r = pcre2_substring_get_bynumber(match_data, number, bufferptr, bufflen);
2821
63.9k
    if (r == PCRE2_ERROR_UNSET) {
2822
21.4k
        *bufferptr = NULL;
2823
21.4k
        *bufflen = 0;
2824
21.4k
        return 0;
2825
21.4k
    }
2826
42.4k
    return r;
2827
63.9k
}
2828
2829
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
2830
3.29k
{
2831
3.29k
    if (!DetectSetupParseRegexesOpts(parse_str, detect_parse, 0)) {
2832
0
        FatalError("pcre compile and study failed");
2833
0
    }
2834
3.29k
}
2835
2836
2837
/*
2838
 * TESTS
2839
 */
2840
2841
#ifdef UNITTESTS
2842
#include "detect-engine-alert.h"
2843
#include "packet.h"
2844
2845
static int SigParseTest01 (void)
2846
{
2847
    int result = 1;
2848
    Signature *sig = NULL;
2849
2850
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2851
    if (de_ctx == NULL)
2852
        goto end;
2853
2854
    sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
2855
    if (sig == NULL)
2856
        result = 0;
2857
2858
end:
2859
    if (sig != NULL) SigFree(de_ctx, sig);
2860
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2861
    return result;
2862
}
2863
2864
static int SigParseTest02 (void)
2865
{
2866
    int result = 0;
2867
    Signature *sig = NULL;
2868
    DetectPort *port = NULL;
2869
2870
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2871
2872
    if (de_ctx == NULL)
2873
        goto end;
2874
2875
    FILE *fd = SCClassConfGenerateValidDummyClassConfigFD01();
2876
    SCClassConfLoadClassificationConfigFile(de_ctx, fd);
2877
2878
    sig = SigInit(de_ctx, "alert tcp any !21:902 -> any any (msg:\"ET MALWARE Suspicious 220 Banner on Local Port\"; content:\"220\"; offset:0; depth:4; pcre:\"/220[- ]/\"; sid:2003055; rev:4;)");
2879
    if (sig == NULL) {
2880
        goto end;
2881
    }
2882
2883
    int r = DetectPortParse(de_ctx, &port, "0:20");
2884
    if (r < 0)
2885
        goto end;
2886
2887
    if (DetectPortCmp(sig->sp, port) == PORT_EQ) {
2888
        result = 1;
2889
    } else {
2890
        DetectPortPrint(port); printf(" != "); DetectPortPrint(sig->sp); printf(": ");
2891
    }
2892
2893
end:
2894
    if (port != NULL)
2895
        DetectPortCleanupList(de_ctx, port);
2896
    if (sig != NULL)
2897
        SigFree(de_ctx, sig);
2898
    if (de_ctx != NULL)
2899
        DetectEngineCtxFree(de_ctx);
2900
    return result;
2901
}
2902
2903
/**
2904
 * \test SigParseTest03 test for invalid direction operator in rule
2905
 */
2906
static int SigParseTest03 (void)
2907
{
2908
    int result = 1;
2909
    Signature *sig = NULL;
2910
2911
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2912
    if (de_ctx == NULL)
2913
        goto end;
2914
2915
    sig = SigInit(de_ctx, "alert tcp 1.2.3.4 any <- !1.2.3.4 any (msg:\"SigParseTest03\"; sid:1;)");
2916
    if (sig != NULL) {
2917
        result = 0;
2918
        printf("expected NULL got sig ptr %p: ",sig);
2919
    }
2920
2921
end:
2922
    if (sig != NULL) SigFree(de_ctx, sig);
2923
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2924
    return result;
2925
}
2926
2927
static int SigParseTest04 (void)
2928
{
2929
    int result = 1;
2930
    Signature *sig = NULL;
2931
2932
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2933
    if (de_ctx == NULL)
2934
        goto end;
2935
2936
    sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024: -> !1.2.3.4 1024: (msg:\"SigParseTest04\"; sid:1;)");
2937
    if (sig == NULL)
2938
        result = 0;
2939
2940
end:
2941
    if (sig != NULL) SigFree(de_ctx, sig);
2942
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2943
    return result;
2944
}
2945
2946
/** \test Port validation */
2947
static int SigParseTest05 (void)
2948
{
2949
    int result = 0;
2950
    Signature *sig = NULL;
2951
2952
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2953
    if (de_ctx == NULL)
2954
        goto end;
2955
2956
    sig = SigInit(de_ctx, "alert tcp 1.2.3.4 1024:65536 -> !1.2.3.4 any (msg:\"SigParseTest05\"; sid:1;)");
2957
    if (sig == NULL) {
2958
        result = 1;
2959
    } else {
2960
        printf("signature didn't fail to parse as we expected: ");
2961
    }
2962
2963
end:
2964
    if (sig != NULL) SigFree(de_ctx, sig);
2965
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
2966
    return result;
2967
}
2968
2969
/** \test Parsing bug debugging at 2010-03-18 */
2970
static int SigParseTest06 (void)
2971
{
2972
    int result = 0;
2973
    Signature *sig = NULL;
2974
2975
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
2976
    if (de_ctx == NULL)
2977
        goto end;
2978
2979
    sig = SigInit(de_ctx, "alert tcp any any -> any any (flow:to_server; content:\"GET\"; nocase; http_method; uricontent:\"/uri/\"; nocase; content:\"Host|3A| abc\"; nocase; sid:1; rev:1;)");
2980
    if (sig != NULL) {
2981
        result = 1;
2982
    } else {
2983
        printf("signature failed to parse: ");
2984
    }
2985
2986
end:
2987
    if (sig != NULL)
2988
        SigFree(de_ctx, sig);
2989
    if (de_ctx != NULL)
2990
        DetectEngineCtxFree(de_ctx);
2991
    return result;
2992
}
2993
2994
/**
2995
 * \test Parsing duplicate sigs.
2996
 */
2997
static int SigParseTest07(void)
2998
{
2999
    int result = 0;
3000
3001
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3002
    if (de_ctx == NULL)
3003
        goto end;
3004
3005
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3006
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3007
3008
    result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL);
3009
3010
end:
3011
    if (de_ctx != NULL)
3012
        DetectEngineCtxFree(de_ctx);
3013
    return result;
3014
}
3015
3016
/**
3017
 * \test Parsing duplicate sigs.
3018
 */
3019
static int SigParseTest08(void)
3020
{
3021
    int result = 0;
3022
3023
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3024
    if (de_ctx == NULL)
3025
        goto end;
3026
3027
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3028
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
3029
3030
    result = (de_ctx->sig_list != NULL && de_ctx->sig_list->next == NULL &&
3031
              de_ctx->sig_list->rev == 2);
3032
3033
end:
3034
    if (de_ctx != NULL)
3035
        DetectEngineCtxFree(de_ctx);
3036
    return result;
3037
}
3038
3039
/**
3040
 * \test Parsing duplicate sigs.
3041
 */
3042
static int SigParseTest09(void)
3043
{
3044
    int result = 1;
3045
3046
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3047
    if (de_ctx == NULL)
3048
        goto end;
3049
3050
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3051
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:2;)");
3052
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:6;)");
3053
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:4;)");
3054
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
3055
    result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
3056
               de_ctx->sig_list->rev == 2);
3057
    if (result == 0)
3058
        goto end;
3059
    result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
3060
               de_ctx->sig_list->next->rev == 6);
3061
    if (result == 0)
3062
        goto end;
3063
3064
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
3065
    result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
3066
               de_ctx->sig_list->rev == 2);
3067
    if (result == 0)
3068
        goto end;
3069
    result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
3070
               de_ctx->sig_list->next->rev == 6);
3071
    if (result == 0)
3072
        goto end;
3073
3074
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:4;)");
3075
    result &= (de_ctx->sig_list != NULL && de_ctx->sig_list->id == 2 &&
3076
               de_ctx->sig_list->rev == 4);
3077
    if (result == 0)
3078
        goto end;
3079
    result &= (de_ctx->sig_list->next != NULL && de_ctx->sig_list->next->id == 1 &&
3080
               de_ctx->sig_list->next->rev == 6);
3081
    if (result == 0)
3082
        goto end;
3083
3084
end:
3085
    if (de_ctx != NULL)
3086
        DetectEngineCtxFree(de_ctx);
3087
    return result;
3088
}
3089
3090
/**
3091
 * \test Parsing duplicate sigs.
3092
 */
3093
static int SigParseTest10(void)
3094
{
3095
    int result = 1;
3096
3097
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3098
    if (de_ctx == NULL)
3099
        goto end;
3100
3101
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:1; rev:1;)");
3102
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:1;)");
3103
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:1;)");
3104
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:4; rev:1;)");
3105
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:5; rev:1;)");
3106
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:3; rev:2;)");
3107
    DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (msg:\"boo\"; sid:2; rev:2;)");
3108
3109
    result &= ((de_ctx->sig_list->id == 2) &&
3110
               (de_ctx->sig_list->next->id == 3) &&
3111
               (de_ctx->sig_list->next->next->id == 5) &&
3112
               (de_ctx->sig_list->next->next->next->id == 4) &&
3113
               (de_ctx->sig_list->next->next->next->next->id == 1));
3114
3115
end:
3116
    if (de_ctx != NULL)
3117
        DetectEngineCtxFree(de_ctx);
3118
    return result;
3119
}
3120
3121
/**
3122
 * \test Parsing sig with trailing space(s) as reported by
3123
 *       Morgan Cox on oisf-users.
3124
 */
3125
static int SigParseTest11(void)
3126
{
3127
    int result = 0;
3128
3129
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3130
    if (de_ctx == NULL)
3131
        goto end;
3132
3133
    Signature *s = NULL;
3134
3135
    s = DetectEngineAppendSig(de_ctx,
3136
            "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking the http link\"; sid:1;) ");
3137
    if (s == NULL) {
3138
        printf("sig 1 didn't parse: ");
3139
        goto end;
3140
    }
3141
3142
    s = DetectEngineAppendSig(de_ctx, "drop tcp any any -> any 80 (msg:\"Snort_Inline is blocking "
3143
                                      "the http link\"; sid:2;)            ");
3144
    if (s == NULL) {
3145
        printf("sig 2 didn't parse: ");
3146
        goto end;
3147
    }
3148
3149
    result = 1;
3150
end:
3151
    if (de_ctx != NULL)
3152
        DetectEngineCtxFree(de_ctx);
3153
    return result;
3154
}
3155
3156
/**
3157
 * \test file_data with rawbytes
3158
 */
3159
static int SigParseTest12(void)
3160
{
3161
    int result = 0;
3162
3163
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3164
    if (de_ctx == NULL)
3165
        goto end;
3166
3167
    Signature *s = NULL;
3168
3169
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (file_data; content:\"abc\"; rawbytes; sid:1;)");
3170
    if (s != NULL) {
3171
        printf("sig 1 should have given an error: ");
3172
        goto end;
3173
    }
3174
3175
    result = 1;
3176
end:
3177
    if (de_ctx != NULL)
3178
        DetectEngineCtxFree(de_ctx);
3179
    return result;
3180
}
3181
3182
/**
3183
 * \test packet/stream sig
3184
 */
3185
static int SigParseTest13(void)
3186
{
3187
    int result = 0;
3188
3189
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3190
    if (de_ctx == NULL)
3191
        goto end;
3192
3193
    Signature *s = NULL;
3194
3195
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; sid:1;)");
3196
    if (s == NULL) {
3197
        printf("sig 1 invalidated: failure");
3198
        goto end;
3199
    }
3200
3201
    if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3202
        printf("sig doesn't have stream flag set\n");
3203
        goto end;
3204
    }
3205
3206
    if (s->flags & SIG_FLAG_REQUIRE_PACKET) {
3207
        printf("sig has packet flag set\n");
3208
        goto end;
3209
    }
3210
3211
    result = 1;
3212
3213
end:
3214
    if (de_ctx != NULL)
3215
        DetectEngineCtxFree(de_ctx);
3216
    return result;
3217
}
3218
3219
/**
3220
 * \test packet/stream sig
3221
 */
3222
static int SigParseTest14(void)
3223
{
3224
    int result = 0;
3225
3226
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3227
    if (de_ctx == NULL)
3228
        goto end;
3229
3230
    Signature *s = NULL;
3231
3232
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; dsize:>0; sid:1;)");
3233
    if (s == NULL) {
3234
        printf("sig 1 invalidated: failure");
3235
        goto end;
3236
    }
3237
3238
    if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3239
        printf("sig doesn't have packet flag set\n");
3240
        goto end;
3241
    }
3242
3243
    if (s->flags & SIG_FLAG_REQUIRE_STREAM) {
3244
        printf("sig has stream flag set\n");
3245
        goto end;
3246
    }
3247
3248
    result = 1;
3249
3250
end:
3251
    if (de_ctx != NULL)
3252
        DetectEngineCtxFree(de_ctx);
3253
    return result;
3254
}
3255
3256
/**
3257
 * \test packet/stream sig
3258
 */
3259
static int SigParseTest15(void)
3260
{
3261
    int result = 0;
3262
3263
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3264
    if (de_ctx == NULL)
3265
        goto end;
3266
3267
    Signature *s = NULL;
3268
3269
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:5; sid:1;)");
3270
    if (s == NULL) {
3271
        printf("sig 1 invalidated: failure");
3272
        goto end;
3273
    }
3274
3275
    if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3276
        printf("sig doesn't have packet flag set\n");
3277
        goto end;
3278
    }
3279
3280
    if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3281
        printf("sig doesn't have stream flag set\n");
3282
        goto end;
3283
    }
3284
3285
    result = 1;
3286
3287
end:
3288
    if (de_ctx != NULL)
3289
        DetectEngineCtxFree(de_ctx);
3290
    return result;
3291
}
3292
3293
/**
3294
 * \test packet/stream sig
3295
 */
3296
static int SigParseTest16(void)
3297
{
3298
    int result = 0;
3299
3300
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3301
    if (de_ctx == NULL)
3302
        goto end;
3303
3304
    Signature *s = NULL;
3305
3306
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; depth:5; sid:1;)");
3307
    if (s == NULL) {
3308
        printf("sig 1 invalidated: failure");
3309
        goto end;
3310
    }
3311
3312
    if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3313
        printf("sig doesn't have packet flag set\n");
3314
        goto end;
3315
    }
3316
3317
    if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3318
        printf("sig doesn't have stream flag set\n");
3319
        goto end;
3320
    }
3321
3322
    result = 1;
3323
3324
end:
3325
    if (de_ctx != NULL)
3326
        DetectEngineCtxFree(de_ctx);
3327
    return result;
3328
}
3329
3330
/**
3331
 * \test packet/stream sig
3332
 */
3333
static int SigParseTest17(void)
3334
{
3335
    int result = 0;
3336
3337
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3338
    if (de_ctx == NULL)
3339
        goto end;
3340
3341
    Signature *s = NULL;
3342
3343
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)");
3344
    if (s == NULL) {
3345
        printf("sig 1 invalidated: failure");
3346
        goto end;
3347
    }
3348
3349
    if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
3350
        printf("sig doesn't have packet flag set\n");
3351
        goto end;
3352
    }
3353
3354
    if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
3355
        printf("sig doesn't have stream flag set\n");
3356
        goto end;
3357
    }
3358
3359
    result = 1;
3360
3361
end:
3362
    if (de_ctx != NULL)
3363
        DetectEngineCtxFree(de_ctx);
3364
    return result;
3365
}
3366
3367
/** \test sid value too large. Bug #779 */
3368
static int SigParseTest18 (void)
3369
{
3370
    int result = 0;
3371
3372
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3373
    if (de_ctx == NULL)
3374
        goto end;
3375
3376
    if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:99999999999999999999;)") != NULL)
3377
        goto end;
3378
3379
    result = 1;
3380
end:
3381
    if (de_ctx != NULL)
3382
        DetectEngineCtxFree(de_ctx);
3383
    return result;
3384
}
3385
3386
/** \test gid value too large. Related to bug #779 */
3387
static int SigParseTest19 (void)
3388
{
3389
    int result = 0;
3390
3391
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3392
    if (de_ctx == NULL)
3393
        goto end;
3394
3395
    if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; gid:99999999999999999999;)") != NULL)
3396
        goto end;
3397
3398
    result = 1;
3399
end:
3400
    if (de_ctx != NULL)
3401
        DetectEngineCtxFree(de_ctx);
3402
    return result;
3403
}
3404
3405
/** \test rev value too large. Related to bug #779 */
3406
static int SigParseTest20 (void)
3407
{
3408
    int result = 0;
3409
3410
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3411
    if (de_ctx == NULL)
3412
        goto end;
3413
3414
    if (DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1; rev:99999999999999999999;)") != NULL)
3415
        goto end;
3416
3417
    result = 1;
3418
end:
3419
    if (de_ctx != NULL)
3420
        DetectEngineCtxFree(de_ctx);
3421
    return result;
3422
}
3423
3424
/** \test address parsing */
3425
static int SigParseTest21 (void)
3426
{
3427
    int result = 0;
3428
3429
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3430
    if (de_ctx == NULL)
3431
        goto end;
3432
3433
    if (DetectEngineAppendSig(de_ctx, "alert tcp [1.2.3.4, 1.2.3.5] any -> !1.2.3.4 any (sid:1;)") == NULL)
3434
        goto end;
3435
3436
    result = 1;
3437
end:
3438
    if (de_ctx != NULL)
3439
        DetectEngineCtxFree(de_ctx);
3440
    return result;
3441
}
3442
3443
/** \test address parsing */
3444
static int SigParseTest22 (void)
3445
{
3446
    int result = 0;
3447
3448
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3449
    if (de_ctx == NULL)
3450
        goto end;
3451
3452
    if (DetectEngineAppendSig(de_ctx, "alert tcp [10.10.10.0/24, !10.10.10.247] any -> [10.10.10.0/24, !10.10.10.247] any (sid:1;)") == NULL)
3453
        goto end;
3454
3455
    result = 1;
3456
end:
3457
    if (de_ctx != NULL)
3458
        DetectEngineCtxFree(de_ctx);
3459
    return result;
3460
}
3461
3462
/**
3463
 * \test rule ending in carriage return
3464
 */
3465
static int SigParseTest23(void)
3466
{
3467
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3468
    FAIL_IF_NULL(de_ctx);
3469
3470
    Signature *s = NULL;
3471
3472
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"abc\"; offset:1; depth:5; sid:1;)\r");
3473
    FAIL_IF_NULL(s);
3474
3475
    DetectEngineCtxFree(de_ctx);
3476
    PASS;
3477
}
3478
3479
/** \test Direction operator validation (invalid) */
3480
static int SigParseBidirecTest06 (void)
3481
{
3482
    int result = 1;
3483
    Signature *sig = NULL;
3484
3485
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3486
    if (de_ctx == NULL)
3487
        goto end;
3488
3489
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any - 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3490
    if (sig == NULL)
3491
        result = 1;
3492
3493
end:
3494
    if (sig != NULL) SigFree(de_ctx, sig);
3495
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3496
    return result;
3497
}
3498
3499
/** \test Direction operator validation (invalid) */
3500
static int SigParseBidirecTest07 (void)
3501
{
3502
    int result = 1;
3503
    Signature *sig = NULL;
3504
3505
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3506
    if (de_ctx == NULL)
3507
        goto end;
3508
3509
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3510
    if (sig == NULL)
3511
        result = 1;
3512
3513
end:
3514
    if (sig != NULL) SigFree(de_ctx, sig);
3515
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3516
    return result;
3517
}
3518
3519
/** \test Direction operator validation (invalid) */
3520
static int SigParseBidirecTest08 (void)
3521
{
3522
    int result = 1;
3523
    Signature *sig = NULL;
3524
3525
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3526
    if (de_ctx == NULL)
3527
        goto end;
3528
3529
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any < 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3530
    if (sig == NULL)
3531
        result = 1;
3532
3533
end:
3534
    if (sig != NULL) SigFree(de_ctx, sig);
3535
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3536
    return result;
3537
}
3538
3539
/** \test Direction operator validation (invalid) */
3540
static int SigParseBidirecTest09 (void)
3541
{
3542
    int result = 1;
3543
    Signature *sig = NULL;
3544
3545
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3546
    if (de_ctx == NULL)
3547
        goto end;
3548
3549
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any > 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3550
    if (sig == NULL)
3551
        result = 1;
3552
3553
end:
3554
    if (sig != NULL) SigFree(de_ctx, sig);
3555
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3556
    return result;
3557
}
3558
3559
/** \test Direction operator validation (invalid) */
3560
static int SigParseBidirecTest10 (void)
3561
{
3562
    int result = 1;
3563
    Signature *sig = NULL;
3564
3565
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3566
    if (de_ctx == NULL)
3567
        goto end;
3568
3569
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3570
    if (sig == NULL)
3571
        result = 1;
3572
3573
end:
3574
    if (sig != NULL) SigFree(de_ctx, sig);
3575
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3576
    return result;
3577
}
3578
3579
/** \test Direction operator validation (invalid) */
3580
static int SigParseBidirecTest11 (void)
3581
{
3582
    int result = 1;
3583
    Signature *sig = NULL;
3584
3585
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3586
    if (de_ctx == NULL)
3587
        goto end;
3588
3589
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >- 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3590
    if (sig == NULL)
3591
        result = 1;
3592
3593
end:
3594
    if (sig != NULL) SigFree(de_ctx, sig);
3595
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3596
    return result;
3597
}
3598
3599
/** \test Direction operator validation (invalid) */
3600
static int SigParseBidirecTest12 (void)
3601
{
3602
    int result = 1;
3603
    Signature *sig = NULL;
3604
3605
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3606
    if (de_ctx == NULL)
3607
        goto end;
3608
3609
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any >< 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3610
    if (sig == NULL)
3611
        result = 1;
3612
3613
end:
3614
    if (sig != NULL) SigFree(de_ctx, sig);
3615
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3616
    return result;
3617
}
3618
3619
/** \test Direction operator validation (valid) */
3620
static int SigParseBidirecTest13 (void)
3621
{
3622
    int result = 1;
3623
    Signature *sig = NULL;
3624
3625
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3626
    if (de_ctx == NULL)
3627
        goto end;
3628
3629
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3630
    if (sig != NULL)
3631
        result = 1;
3632
3633
end:
3634
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3635
    return result;
3636
}
3637
3638
/** \test Direction operator validation (valid) */
3639
static int SigParseBidirecTest14 (void)
3640
{
3641
    int result = 1;
3642
    Signature *sig = NULL;
3643
3644
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3645
    if (de_ctx == NULL)
3646
        goto end;
3647
3648
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> 192.168.1.5 any (msg:\"SigParseBidirecTest05\"; sid:1;)");
3649
    if (sig != NULL)
3650
        result = 1;
3651
3652
end:
3653
    if (de_ctx != NULL) DetectEngineCtxFree(de_ctx);
3654
    return result;
3655
}
3656
3657
/** \test Ensure that we don't set bidirectional in a
3658
 *         normal (one direction) Signature
3659
 */
3660
static int SigTestBidirec01 (void)
3661
{
3662
    Signature *sig = NULL;
3663
    int result = 0;
3664
3665
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3666
    if (de_ctx == NULL)
3667
        goto end;
3668
3669
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 -> !1.2.3.4 any (msg:\"SigTestBidirec01\"; sid:1;)");
3670
    if (sig == NULL)
3671
        goto end;
3672
    if (sig->next != NULL)
3673
        goto end;
3674
    if (sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC)
3675
        goto end;
3676
    if (de_ctx->signum != 1)
3677
        goto end;
3678
3679
    result = 1;
3680
3681
end:
3682
    if (de_ctx != NULL) {
3683
        SigCleanSignatures(de_ctx);
3684
        SigGroupCleanup(de_ctx);
3685
        DetectEngineCtxFree(de_ctx);
3686
    }
3687
    return result;
3688
}
3689
3690
/** \test Ensure that we set a bidirectional Signature correctly */
3691
static int SigTestBidirec02 (void)
3692
{
3693
    int result = 0;
3694
    Signature *sig = NULL;
3695
    Signature *copy = NULL;
3696
3697
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3698
    if (de_ctx == NULL)
3699
        goto end;
3700
3701
    de_ctx->flags |= DE_QUIET;
3702
3703
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 1.2.3.4 1024:65535 <> !1.2.3.4 any (msg:\"SigTestBidirec02\"; sid:1;)");
3704
    if (sig == NULL)
3705
        goto end;
3706
    if (de_ctx->sig_list != sig)
3707
        goto end;
3708
    if (!(sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3709
        goto end;
3710
    if (sig->next == NULL)
3711
        goto end;
3712
    if (de_ctx->signum != 2)
3713
        goto end;
3714
    copy = sig->next;
3715
    if (copy->next != NULL)
3716
        goto end;
3717
    if (!(copy->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3718
        goto end;
3719
3720
    result = 1;
3721
3722
end:
3723
    if (de_ctx != NULL) {
3724
        SigCleanSignatures(de_ctx);
3725
        SigGroupCleanup(de_ctx);
3726
        DetectEngineCtxFree(de_ctx);
3727
    }
3728
3729
    return result;
3730
}
3731
3732
/** \test Ensure that we set a bidirectional Signature correctly
3733
*         and we install it with the rest of the signatures, checking
3734
*         also that it match with the correct addr directions
3735
*/
3736
static int SigTestBidirec03 (void)
3737
{
3738
    int result = 0;
3739
    Signature *sig = NULL;
3740
    Packet *p = NULL;
3741
3742
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3743
    if (de_ctx == NULL)
3744
        goto end;
3745
3746
    de_ctx->flags |= DE_QUIET;
3747
3748
    const char *sigs[3];
3749
    sigs[0] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)";
3750
    sigs[1] = "alert tcp any any <> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)";
3751
    sigs[2] = "alert tcp any any -> 192.168.1.1 any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)";
3752
    UTHAppendSigs(de_ctx, sigs, 3);
3753
3754
    /* Checking that bidirectional rules are set correctly */
3755
    sig = de_ctx->sig_list;
3756
    if (sig == NULL)
3757
        goto end;
3758
    if (sig->next == NULL)
3759
        goto end;
3760
    if (sig->next->next == NULL)
3761
        goto end;
3762
    if (sig->next->next->next == NULL)
3763
        goto end;
3764
    if (sig->next->next->next->next != NULL)
3765
        goto end;
3766
    if (de_ctx->signum != 4)
3767
        goto end;
3768
3769
    uint8_t rawpkt1_ether[] = {
3770
        0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3771
        0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3772
        0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3773
        0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3774
        0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3775
        0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3776
        0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3777
        0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3778
        0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3779
        0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3780
        0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3781
        0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3782
        0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3783
        0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3784
        0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3785
        0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3786
        0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3787
        0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3788
        0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3789
        0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3790
        0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3791
        0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3792
        0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3793
        0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3794
        0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3795
        0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3796
        0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3797
        0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3798
        0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3799
        0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3800
        0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3801
        0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3802
        0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3803
        0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3804
        0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3805
        0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3806
        0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3807
        0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3808
        0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3809
        0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3810
        0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3811
        0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3812
        0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3813
        0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3814
        0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3815
        0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3816
        0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3817
        0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3818
        0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3819
        0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3820
        0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3821
        0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3822
        0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3823
        0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3824
        0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3825
3826
    FlowInitConfig(FLOW_QUIET);
3827
    p = UTHBuildPacketFromEth(rawpkt1_ether, sizeof(rawpkt1_ether));
3828
    if (p == NULL) {
3829
        SCLogDebug("Error building packet");
3830
        goto end;
3831
    }
3832
    UTHMatchPackets(de_ctx, &p, 1);
3833
3834
    uint32_t sids[3] = {1, 2, 3};
3835
    uint32_t results[3] = {1, 1, 1};
3836
    result = UTHCheckPacketMatchResults(p, sids, results, 1);
3837
3838
end:
3839
    if (p != NULL) {
3840
        PacketRecycle(p);
3841
        SCFree(p);
3842
    }
3843
    FlowShutdown();
3844
    return result;
3845
}
3846
3847
/** \test Ensure that we set a bidirectional Signature correctly
3848
*         and we install it with the rest of the signatures, checking
3849
*         also that it match with the correct addr directions
3850
*/
3851
static int SigTestBidirec04 (void)
3852
{
3853
    int result = 0;
3854
    Signature *sig = NULL;
3855
    Packet *p = NULL;
3856
3857
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
3858
    if (de_ctx == NULL)
3859
        goto end;
3860
3861
    de_ctx->flags |= DE_QUIET;
3862
3863
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 1\"; sid:1;)");
3864
    if (sig == NULL)
3865
        goto end;
3866
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any <> any any (msg:\"SigTestBidirec03 sid 2 bidirectional\"; sid:2;)");
3867
    if (sig == NULL)
3868
        goto end;
3869
    if ( !(sig->init_data->init_flags & SIG_FLAG_INIT_BIDIREC))
3870
        goto end;
3871
    if (sig->next == NULL)
3872
        goto end;
3873
    if (sig->next->next == NULL)
3874
        goto end;
3875
    if (sig->next->next->next != NULL)
3876
        goto end;
3877
    if (de_ctx->signum != 3)
3878
        goto end;
3879
3880
    sig = DetectEngineAppendSig(de_ctx, "alert tcp 192.168.1.1 any -> any any (msg:\"SigTestBidirec03 sid 3\"; sid:3;)");
3881
    if (sig == NULL)
3882
        goto end;
3883
    if (sig->next == NULL)
3884
        goto end;
3885
    if (sig->next->next == NULL)
3886
        goto end;
3887
    if (sig->next->next->next == NULL)
3888
        goto end;
3889
    if (sig->next->next->next->next != NULL)
3890
        goto end;
3891
    if (de_ctx->signum != 4)
3892
        goto end;
3893
3894
    uint8_t rawpkt1_ether[] = {
3895
        0x00,0x50,0x56,0xea,0x00,0xbd,0x00,0x0c,
3896
        0x29,0x40,0xc8,0xb5,0x08,0x00,0x45,0x00,
3897
        0x01,0xa8,0xb9,0xbb,0x40,0x00,0x40,0x06,
3898
        0xe0,0xbf,0xc0,0xa8,0x1c,0x83,0xc0,0xa8,
3899
        0x01,0x01,0xb9,0x0a,0x00,0x50,0x6f,0xa2,
3900
        0x92,0xed,0x7b,0xc1,0xd3,0x4d,0x50,0x18,
3901
        0x16,0xd0,0xa0,0x6f,0x00,0x00,0x47,0x45,
3902
        0x54,0x20,0x2f,0x20,0x48,0x54,0x54,0x50,
3903
        0x2f,0x31,0x2e,0x31,0x0d,0x0a,0x48,0x6f,
3904
        0x73,0x74,0x3a,0x20,0x31,0x39,0x32,0x2e,
3905
        0x31,0x36,0x38,0x2e,0x31,0x2e,0x31,0x0d,
3906
        0x0a,0x55,0x73,0x65,0x72,0x2d,0x41,0x67,
3907
        0x65,0x6e,0x74,0x3a,0x20,0x4d,0x6f,0x7a,
3908
        0x69,0x6c,0x6c,0x61,0x2f,0x35,0x2e,0x30,
3909
        0x20,0x28,0x58,0x31,0x31,0x3b,0x20,0x55,
3910
        0x3b,0x20,0x4c,0x69,0x6e,0x75,0x78,0x20,
3911
        0x78,0x38,0x36,0x5f,0x36,0x34,0x3b,0x20,
3912
        0x65,0x6e,0x2d,0x55,0x53,0x3b,0x20,0x72,
3913
        0x76,0x3a,0x31,0x2e,0x39,0x2e,0x30,0x2e,
3914
        0x31,0x34,0x29,0x20,0x47,0x65,0x63,0x6b,
3915
        0x6f,0x2f,0x32,0x30,0x30,0x39,0x30,0x39,
3916
        0x30,0x32,0x31,0x37,0x20,0x55,0x62,0x75,
3917
        0x6e,0x74,0x75,0x2f,0x39,0x2e,0x30,0x34,
3918
        0x20,0x28,0x6a,0x61,0x75,0x6e,0x74,0x79,
3919
        0x29,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,
3920
        0x78,0x2f,0x33,0x2e,0x30,0x2e,0x31,0x34,
3921
        0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,0x74,
3922
        0x3a,0x20,0x74,0x65,0x78,0x74,0x2f,0x68,
3923
        0x74,0x6d,0x6c,0x2c,0x61,0x70,0x70,0x6c,
3924
        0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,
3925
        0x78,0x68,0x74,0x6d,0x6c,0x2b,0x78,0x6d,
3926
        0x6c,0x2c,0x61,0x70,0x70,0x6c,0x69,0x63,
3927
        0x61,0x74,0x69,0x6f,0x6e,0x2f,0x78,0x6d,
3928
        0x6c,0x3b,0x71,0x3d,0x30,0x2e,0x39,0x2c,
3929
        0x2a,0x2f,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3930
        0x38,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3931
        0x74,0x2d,0x4c,0x61,0x6e,0x67,0x75,0x61,
3932
        0x67,0x65,0x3a,0x20,0x65,0x6e,0x2d,0x75,
3933
        0x73,0x2c,0x65,0x6e,0x3b,0x71,0x3d,0x30,
3934
        0x2e,0x35,0x0d,0x0a,0x41,0x63,0x63,0x65,
3935
        0x70,0x74,0x2d,0x45,0x6e,0x63,0x6f,0x64,
3936
        0x69,0x6e,0x67,0x3a,0x20,0x67,0x7a,0x69,
3937
        0x70,0x2c,0x64,0x65,0x66,0x6c,0x61,0x74,
3938
        0x65,0x0d,0x0a,0x41,0x63,0x63,0x65,0x70,
3939
        0x74,0x2d,0x43,0x68,0x61,0x72,0x73,0x65,
3940
        0x74,0x3a,0x20,0x49,0x53,0x4f,0x2d,0x38,
3941
        0x38,0x35,0x39,0x2d,0x31,0x2c,0x75,0x74,
3942
        0x66,0x2d,0x38,0x3b,0x71,0x3d,0x30,0x2e,
3943
        0x37,0x2c,0x2a,0x3b,0x71,0x3d,0x30,0x2e,
3944
        0x37,0x0d,0x0a,0x4b,0x65,0x65,0x70,0x2d,
3945
        0x41,0x6c,0x69,0x76,0x65,0x3a,0x20,0x33,
3946
        0x30,0x30,0x0d,0x0a,0x43,0x6f,0x6e,0x6e,
3947
        0x65,0x63,0x74,0x69,0x6f,0x6e,0x3a,0x20,
3948
        0x6b,0x65,0x65,0x70,0x2d,0x61,0x6c,0x69,
3949
        0x76,0x65,0x0d,0x0a,0x0d,0x0a }; /* end rawpkt1_ether */
3950
3951
    p = PacketGetFromAlloc();
3952
    if (unlikely(p == NULL))
3953
        return 0;
3954
    DecodeThreadVars dtv;
3955
    ThreadVars th_v;
3956
    DetectEngineThreadCtx *det_ctx;
3957
3958
    memset(&th_v, 0, sizeof(th_v));
3959
3960
    FlowInitConfig(FLOW_QUIET);
3961
    DecodeEthernet(&th_v, &dtv, p, rawpkt1_ether, sizeof(rawpkt1_ether));
3962
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
3963
3964
    /* At this point we have a list of 4 signatures. The last one
3965
       is a copy of the second one. If we receive a packet
3966
       with source 192.168.1.1 80, all the sids should match */
3967
3968
    SigGroupBuild(de_ctx);
3969
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
3970
3971
    /* only sid 2 should match with a packet going to 192.168.1.1 port 80 */
3972
    if (PacketAlertCheck(p, 1) <= 0 && PacketAlertCheck(p, 3) <= 0 &&
3973
        PacketAlertCheck(p, 2) == 1) {
3974
        result = 1;
3975
    }
3976
3977
    if (p != NULL) {
3978
        PacketRecycle(p);
3979
    }
3980
    FlowShutdown();
3981
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
3982
3983
end:
3984
    if (de_ctx != NULL) {
3985
        SigCleanSignatures(de_ctx);
3986
        SigGroupCleanup(de_ctx);
3987
        DetectEngineCtxFree(de_ctx);
3988
    }
3989
3990
    if (p != NULL)
3991
        SCFree(p);
3992
    return result;
3993
}
3994
3995
/**
3996
 * \test check that we don't allow invalid negation options
3997
 */
3998
static int SigParseTestNegation01 (void)
3999
{
4000
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4001
    FAIL_IF_NULL(de_ctx);
4002
    de_ctx->flags |= DE_QUIET;
4003
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp !any any -> any any (sid:1;)");
4004
    FAIL_IF_NOT_NULL(s);
4005
    DetectEngineCtxFree(de_ctx);
4006
    PASS;
4007
}
4008
4009
/**
4010
 * \test check that we don't allow invalid negation options
4011
 */
4012
static int SigParseTestNegation02 (void)
4013
{
4014
    int result = 0;
4015
    DetectEngineCtx *de_ctx;
4016
    Signature *s=NULL;
4017
4018
    de_ctx = DetectEngineCtxInit();
4019
    if (de_ctx == NULL)
4020
        goto end;
4021
    de_ctx->flags |= DE_QUIET;
4022
4023
    s = SigInit(de_ctx,"alert tcp any !any -> any any (msg:\"SigTest41-02 src ip is !any \"; classtype:misc-activity; sid:410002; rev:1;)");
4024
    if (s != NULL) {
4025
        SigFree(de_ctx, s);
4026
        goto end;
4027
    }
4028
4029
    result = 1;
4030
end:
4031
    if (de_ctx != NULL)
4032
        DetectEngineCtxFree(de_ctx);
4033
    return result;
4034
}
4035
/**
4036
 * \test check that we don't allow invalid negation options
4037
 */
4038
static int SigParseTestNegation03 (void)
4039
{
4040
    int result = 0;
4041
    DetectEngineCtx *de_ctx;
4042
    Signature *s=NULL;
4043
4044
    de_ctx = DetectEngineCtxInit();
4045
    if (de_ctx == NULL)
4046
        goto end;
4047
    de_ctx->flags |= DE_QUIET;
4048
4049
    s = SigInit(de_ctx,"alert tcp any any -> any [80:!80] (msg:\"SigTest41-03 dst port [80:!80] \"; classtype:misc-activity; sid:410003; rev:1;)");
4050
    if (s != NULL) {
4051
        SigFree(de_ctx, s);
4052
        goto end;
4053
    }
4054
4055
    result = 1;
4056
end:
4057
    if (de_ctx != NULL)
4058
        DetectEngineCtxFree(de_ctx);
4059
    return result;
4060
}
4061
/**
4062
 * \test check that we don't allow invalid negation options
4063
 */
4064
static int SigParseTestNegation04 (void)
4065
{
4066
    int result = 0;
4067
    DetectEngineCtx *de_ctx;
4068
    Signature *s=NULL;
4069
4070
    de_ctx = DetectEngineCtxInit();
4071
    if (de_ctx == NULL)
4072
        goto end;
4073
    de_ctx->flags |= DE_QUIET;
4074
4075
    s = SigInit(de_ctx,"alert tcp any any -> any [80,!80] (msg:\"SigTest41-03 dst port [80:!80] \"; classtype:misc-activity; sid:410003; rev:1;)");
4076
    if (s != NULL) {
4077
        SigFree(de_ctx, s);
4078
        goto end;
4079
    }
4080
4081
    result = 1;
4082
end:
4083
    if (de_ctx != NULL)
4084
        DetectEngineCtxFree(de_ctx);
4085
    return result;
4086
}
4087
/**
4088
 * \test check that we don't allow invalid negation options
4089
 */
4090
static int SigParseTestNegation05 (void)
4091
{
4092
    int result = 0;
4093
    DetectEngineCtx *de_ctx;
4094
    Signature *s=NULL;
4095
4096
    de_ctx = DetectEngineCtxInit();
4097
    if (de_ctx == NULL)
4098
        goto end;
4099
    de_ctx->flags |= DE_QUIET;
4100
4101
    s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.2,!192.168.0.2] any (msg:\"SigTest41-04 dst ip [192.168.0.2,!192.168.0.2] \"; classtype:misc-activity; sid:410004; rev:1;)");
4102
    if (s != NULL) {
4103
        SigFree(de_ctx, s);
4104
        goto end;
4105
    }
4106
4107
    result = 1;
4108
end:
4109
    if (de_ctx != NULL)
4110
        DetectEngineCtxFree(de_ctx);
4111
    return result;
4112
}
4113
/**
4114
 * \test check that we don't allow invalid negation options
4115
 */
4116
static int SigParseTestNegation06 (void)
4117
{
4118
    int result = 0;
4119
    DetectEngineCtx *de_ctx;
4120
    Signature *s=NULL;
4121
4122
    de_ctx = DetectEngineCtxInit();
4123
    if (de_ctx == NULL)
4124
        goto end;
4125
    de_ctx->flags |= DE_QUIET;
4126
4127
    s = SigInit(de_ctx,"alert tcp any any -> any [100:1000,!1:20000] (msg:\"SigTest41-05 dst port [100:1000,!1:20000] \"; classtype:misc-activity; sid:410005; rev:1;)");
4128
    if (s != NULL) {
4129
        SigFree(de_ctx, s);
4130
        goto end;
4131
    }
4132
4133
    result = 1;
4134
end:
4135
    if (de_ctx != NULL)
4136
        DetectEngineCtxFree(de_ctx);
4137
    return result;
4138
}
4139
4140
/**
4141
 * \test check that we don't allow invalid negation options
4142
 */
4143
static int SigParseTestNegation07 (void)
4144
{
4145
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4146
    FAIL_IF_NULL(de_ctx);
4147
    de_ctx->flags |= DE_QUIET;
4148
    Signature *s = DetectEngineAppendSig(
4149
            de_ctx, "alert tcp any any -> [192.168.0.2,!192.168.0.0/24] any (sid:410006;)");
4150
    FAIL_IF_NOT_NULL(s);
4151
    DetectEngineCtxFree(de_ctx);
4152
    PASS;
4153
}
4154
4155
/**
4156
 * \test check valid negation bug 1079
4157
 */
4158
static int SigParseTestNegation08 (void)
4159
{
4160
    int result = 0;
4161
    DetectEngineCtx *de_ctx;
4162
    Signature *s=NULL;
4163
4164
    de_ctx = DetectEngineCtxInit();
4165
    if (de_ctx == NULL)
4166
        goto end;
4167
    de_ctx->flags |= DE_QUIET;
4168
4169
    s = SigInit(de_ctx,"alert tcp any any -> [192.168.0.0/16,!192.168.0.0/24] any (sid:410006; rev:1;)");
4170
    if (s == NULL) {
4171
        goto end;
4172
    }
4173
4174
    result = 1;
4175
end:
4176
    if (de_ctx != NULL)
4177
        DetectEngineCtxFree(de_ctx);
4178
    return result;
4179
}
4180
4181
/**
4182
 * \test mpm
4183
 */
4184
static int SigParseTestMpm01 (void)
4185
{
4186
    int result = 0;
4187
    Signature *sig = NULL;
4188
4189
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4190
    if (de_ctx == NULL)
4191
        goto end;
4192
4193
    sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; sid:1;)");
4194
    if (sig == NULL) {
4195
        printf("sig failed to init: ");
4196
        goto end;
4197
    }
4198
4199
    if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
4200
        printf("sig doesn't have content list: ");
4201
        goto end;
4202
    }
4203
4204
    result = 1;
4205
end:
4206
    if (sig != NULL)
4207
        SigFree(de_ctx, sig);
4208
    DetectEngineCtxFree(de_ctx);
4209
    return result;
4210
}
4211
4212
/**
4213
 * \test mpm
4214
 */
4215
static int SigParseTestMpm02 (void)
4216
{
4217
    int result = 0;
4218
    Signature *sig = NULL;
4219
4220
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4221
    if (de_ctx == NULL)
4222
        goto end;
4223
4224
    sig = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"mpm test\"; content:\"abcd\"; content:\"abcdef\"; sid:1;)");
4225
    if (sig == NULL) {
4226
        printf("sig failed to init: ");
4227
        goto end;
4228
    }
4229
4230
    if (sig->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
4231
        printf("sig doesn't have content list: ");
4232
        goto end;
4233
    }
4234
4235
    result = 1;
4236
end:
4237
    if (sig != NULL)
4238
        SigFree(de_ctx, sig);
4239
    DetectEngineCtxFree(de_ctx);
4240
    return result;
4241
}
4242
4243
/**
4244
 * \test test tls (app layer) rule
4245
 */
4246
static int SigParseTestAppLayerTLS01(void)
4247
{
4248
    int result = 0;
4249
    DetectEngineCtx *de_ctx;
4250
    Signature *s=NULL;
4251
4252
    de_ctx = DetectEngineCtxInit();
4253
    if (de_ctx == NULL)
4254
        goto end;
4255
    de_ctx->flags |= DE_QUIET;
4256
4257
    s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS01 \"; sid:410006; rev:1;)");
4258
    if (s == NULL) {
4259
        printf("parsing sig failed: ");
4260
        goto end;
4261
    }
4262
4263
    if (s->alproto == 0) {
4264
        printf("alproto not set: ");
4265
        goto end;
4266
    }
4267
4268
    result = 1;
4269
end:
4270
    if (s != NULL)
4271
        SigFree(de_ctx, s);
4272
    if (de_ctx != NULL)
4273
        DetectEngineCtxFree(de_ctx);
4274
4275
    return result;
4276
}
4277
4278
/**
4279
 * \test test tls (app layer) rule
4280
 */
4281
static int SigParseTestAppLayerTLS02(void)
4282
{
4283
    int result = 0;
4284
    DetectEngineCtx *de_ctx;
4285
    Signature *s=NULL;
4286
4287
    de_ctx = DetectEngineCtxInit();
4288
    if (de_ctx == NULL)
4289
        goto end;
4290
    de_ctx->flags |= DE_QUIET;
4291
4292
    s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS02 \"; tls.version:1.0; sid:410006; rev:1;)");
4293
    if (s == NULL) {
4294
        printf("parsing sig failed: ");
4295
        goto end;
4296
    }
4297
4298
    if (s->alproto == 0) {
4299
        printf("alproto not set: ");
4300
        goto end;
4301
    }
4302
4303
    result = 1;
4304
end:
4305
    if (s != NULL)
4306
        SigFree(de_ctx, s);
4307
    if (de_ctx != NULL)
4308
        DetectEngineCtxFree(de_ctx);
4309
    return result;
4310
}
4311
4312
/**
4313
 * \test test tls (app layer) rule
4314
 */
4315
static int SigParseTestAppLayerTLS03(void)
4316
{
4317
    int result = 0;
4318
    DetectEngineCtx *de_ctx;
4319
    Signature *s=NULL;
4320
4321
    de_ctx = DetectEngineCtxInit();
4322
    if (de_ctx == NULL)
4323
        goto end;
4324
    de_ctx->flags |= DE_QUIET;
4325
4326
    s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS03 \"; tls.version:2.5; sid:410006; rev:1;)");
4327
    if (s != NULL) {
4328
        SigFree(de_ctx, s);
4329
        goto end;
4330
    }
4331
4332
    result = 1;
4333
end:
4334
    if (de_ctx != NULL)
4335
        DetectEngineCtxFree(de_ctx);
4336
    return result;
4337
}
4338
4339
static int SigParseTestUnbalancedQuotes01(void)
4340
{
4341
    DetectEngineCtx *de_ctx;
4342
    Signature *s;
4343
4344
    de_ctx = DetectEngineCtxInit();
4345
    FAIL_IF_NULL(de_ctx);
4346
    de_ctx->flags |= DE_QUIET;
4347
4348
    s = SigInit(de_ctx,
4349
            "alert http any any -> any any (msg:\"SigParseTestUnbalancedQuotes01\"; "
4350
            "pcre:\"/\\/[a-z]+\\.php\\?[a-z]+?=\\d{7}&[a-z]+?=\\d{7,8}$/U\" "
4351
            "flowbits:set,et.exploitkitlanding; classtype:trojan-activity; sid:2017078; rev:5;)");
4352
    FAIL_IF_NOT_NULL(s);
4353
4354
    PASS;
4355
}
4356
4357
static int SigParseTestContentGtDsize01(void)
4358
{
4359
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4360
    FAIL_IF_NULL(de_ctx);
4361
    de_ctx->flags |= DE_QUIET;
4362
4363
    Signature *s = SigInit(de_ctx,
4364
            "alert http any any -> any any ("
4365
            "dsize:21; content:\"0123456789001234567890|00 00|\"; "
4366
            "sid:1; rev:1;)");
4367
    FAIL_IF_NOT_NULL(s);
4368
4369
    PASS;
4370
}
4371
4372
static int SigParseTestContentGtDsize02(void)
4373
{
4374
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4375
    FAIL_IF_NULL(de_ctx);
4376
    de_ctx->flags |= DE_QUIET;
4377
4378
    Signature *s = SigInit(de_ctx,
4379
            "alert http any any -> any any ("
4380
            "dsize:21; content:\"0123456789|00 00|\"; offset:10; "
4381
            "sid:1; rev:1;)");
4382
    FAIL_IF_NOT_NULL(s);
4383
4384
    PASS;
4385
}
4386
4387
static int CountSigsWithSid(const DetectEngineCtx *de_ctx, const uint32_t sid)
4388
{
4389
    int cnt = 0;
4390
    for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
4391
        if (sid == s->id)
4392
            cnt++;
4393
    }
4394
    return cnt;
4395
}
4396
4397
static int SigParseBidirWithSameSrcAndDest01(void)
4398
{
4399
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4400
    FAIL_IF_NULL(de_ctx);
4401
    de_ctx->flags |= DE_QUIET;
4402
4403
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any <> any any (sid:1;)");
4404
    FAIL_IF_NULL(s);
4405
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 1) == 1);
4406
    FAIL_IF(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4407
4408
    s = DetectEngineAppendSig(de_ctx, "alert tcp any [80, 81] <> any [81, 80] (sid:2;)");
4409
    FAIL_IF_NULL(s);
4410
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 2) == 1);
4411
    FAIL_IF(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4412
4413
    s = DetectEngineAppendSig(de_ctx,
4414
            "alert tcp [1.2.3.4, 5.6.7.8] [80, 81] <> [5.6.7.8, 1.2.3.4] [81, 80] (sid:3;)");
4415
    FAIL_IF_NULL(s);
4416
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 3) == 1);
4417
    FAIL_IF(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4418
4419
    DetectEngineCtxFree(de_ctx);
4420
    PASS;
4421
}
4422
4423
static int SigParseBidirWithSameSrcAndDest02(void)
4424
{
4425
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4426
    FAIL_IF_NULL(de_ctx);
4427
    de_ctx->flags |= DE_QUIET;
4428
4429
    // Source is a subset of destination
4430
    Signature *s = DetectEngineAppendSig(
4431
            de_ctx, "alert tcp 1.2.3.4 any <> [1.2.3.4, 5.6.7.8, ::1] any (sid:1;)");
4432
    FAIL_IF_NULL(s);
4433
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 1) == 2);
4434
    FAIL_IF_NOT(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4435
4436
    // Source is a subset of destination
4437
    s = DetectEngineAppendSig(
4438
            de_ctx, "alert tcp [1.2.3.4, ::1] [80, 81, 82] <> [1.2.3.4, ::1] [80, 81] (sid:2;)");
4439
    FAIL_IF_NULL(s);
4440
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 2) == 2);
4441
    FAIL_IF_NOT(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4442
4443
    // Source intersects with destination
4444
    s = DetectEngineAppendSig(de_ctx,
4445
            "alert tcp [1.2.3.4, ::1, ABCD:AAAA::1] [80] <> [1.2.3.4, ::1] [80, 81] (sid:3;)");
4446
    FAIL_IF_NULL(s);
4447
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 3) == 2);
4448
    FAIL_IF_NOT(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4449
4450
    // mix in negation, these are the same
4451
    s = DetectEngineAppendSig(
4452
            de_ctx, "alert tcp [!1.2.3.4, 1.2.3.0/24] any <> [1.2.3.0/24, !1.2.3.4] any (sid:4;)");
4453
    FAIL_IF_NULL(s);
4454
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 4) == 1);
4455
    FAIL_IF(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4456
4457
    // mix in negation, these are not the same
4458
    s = DetectEngineAppendSig(
4459
            de_ctx, "alert tcp [1.2.3.4, 1.2.3.0/24] any <> [1.2.3.0/24, !1.2.3.4] any (sid:5;)");
4460
    FAIL_IF_NULL(s);
4461
    FAIL_IF_NOT(CountSigsWithSid(de_ctx, 5) == 2);
4462
    FAIL_IF_NOT(s->init_data->init_flags & SIG_FLAG_INIT_BIDIREC);
4463
4464
    DetectEngineCtxFree(de_ctx);
4465
    PASS;
4466
}
4467
4468
static int SigParseTestActionReject(void)
4469
{
4470
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4471
    FAIL_IF_NULL(de_ctx);
4472
4473
    Signature *sig = DetectEngineAppendSig(
4474
            de_ctx, "reject tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
4475
#ifdef HAVE_LIBNET11
4476
    FAIL_IF_NULL(sig);
4477
    FAIL_IF_NOT((sig->action & (ACTION_DROP | ACTION_REJECT)) == (ACTION_DROP | ACTION_REJECT));
4478
#else
4479
    FAIL_IF_NOT_NULL(sig);
4480
#endif
4481
4482
    DetectEngineCtxFree(de_ctx);
4483
    PASS;
4484
}
4485
4486
static int SigParseTestActionDrop(void)
4487
{
4488
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
4489
    FAIL_IF_NULL(de_ctx);
4490
4491
    Signature *sig = DetectEngineAppendSig(
4492
            de_ctx, "drop tcp 1.2.3.4 any -> !1.2.3.4 any (msg:\"SigParseTest01\"; sid:1;)");
4493
    FAIL_IF_NULL(sig);
4494
    FAIL_IF_NOT(sig->action & ACTION_DROP);
4495
4496
    DetectEngineCtxFree(de_ctx);
4497
    PASS;
4498
}
4499
4500
#endif /* UNITTESTS */
4501
4502
#ifdef UNITTESTS
4503
void DetectParseRegisterTests (void);
4504
#include "tests/detect-parse.c"
4505
#endif
4506
4507
void SigParseRegisterTests(void)
4508
0
{
4509
#ifdef UNITTESTS
4510
    DetectParseRegisterTests();
4511
4512
    UtRegisterTest("SigParseTest01", SigParseTest01);
4513
    UtRegisterTest("SigParseTest02", SigParseTest02);
4514
    UtRegisterTest("SigParseTest03", SigParseTest03);
4515
    UtRegisterTest("SigParseTest04", SigParseTest04);
4516
    UtRegisterTest("SigParseTest05", SigParseTest05);
4517
    UtRegisterTest("SigParseTest06", SigParseTest06);
4518
    UtRegisterTest("SigParseTest07", SigParseTest07);
4519
    UtRegisterTest("SigParseTest08", SigParseTest08);
4520
    UtRegisterTest("SigParseTest09", SigParseTest09);
4521
    UtRegisterTest("SigParseTest10", SigParseTest10);
4522
    UtRegisterTest("SigParseTest11", SigParseTest11);
4523
    UtRegisterTest("SigParseTest12", SigParseTest12);
4524
    UtRegisterTest("SigParseTest13", SigParseTest13);
4525
    UtRegisterTest("SigParseTest14", SigParseTest14);
4526
    UtRegisterTest("SigParseTest15", SigParseTest15);
4527
    UtRegisterTest("SigParseTest16", SigParseTest16);
4528
    UtRegisterTest("SigParseTest17", SigParseTest17);
4529
    UtRegisterTest("SigParseTest18", SigParseTest18);
4530
    UtRegisterTest("SigParseTest19", SigParseTest19);
4531
    UtRegisterTest("SigParseTest20", SigParseTest20);
4532
    UtRegisterTest("SigParseTest21 -- address with space", SigParseTest21);
4533
    UtRegisterTest("SigParseTest22 -- address with space", SigParseTest22);
4534
    UtRegisterTest("SigParseTest23 -- carriage return", SigParseTest23);
4535
4536
    UtRegisterTest("SigParseBidirecTest06", SigParseBidirecTest06);
4537
    UtRegisterTest("SigParseBidirecTest07", SigParseBidirecTest07);
4538
    UtRegisterTest("SigParseBidirecTest08", SigParseBidirecTest08);
4539
    UtRegisterTest("SigParseBidirecTest09", SigParseBidirecTest09);
4540
    UtRegisterTest("SigParseBidirecTest10", SigParseBidirecTest10);
4541
    UtRegisterTest("SigParseBidirecTest11", SigParseBidirecTest11);
4542
    UtRegisterTest("SigParseBidirecTest12", SigParseBidirecTest12);
4543
    UtRegisterTest("SigParseBidirecTest13", SigParseBidirecTest13);
4544
    UtRegisterTest("SigParseBidirecTest14", SigParseBidirecTest14);
4545
    UtRegisterTest("SigTestBidirec01", SigTestBidirec01);
4546
    UtRegisterTest("SigTestBidirec02", SigTestBidirec02);
4547
    UtRegisterTest("SigTestBidirec03", SigTestBidirec03);
4548
    UtRegisterTest("SigTestBidirec04", SigTestBidirec04);
4549
    UtRegisterTest("SigParseTestNegation01", SigParseTestNegation01);
4550
    UtRegisterTest("SigParseTestNegation02", SigParseTestNegation02);
4551
    UtRegisterTest("SigParseTestNegation03", SigParseTestNegation03);
4552
    UtRegisterTest("SigParseTestNegation04", SigParseTestNegation04);
4553
    UtRegisterTest("SigParseTestNegation05", SigParseTestNegation05);
4554
    UtRegisterTest("SigParseTestNegation06", SigParseTestNegation06);
4555
    UtRegisterTest("SigParseTestNegation07", SigParseTestNegation07);
4556
    UtRegisterTest("SigParseTestNegation08", SigParseTestNegation08);
4557
    UtRegisterTest("SigParseTestMpm01", SigParseTestMpm01);
4558
    UtRegisterTest("SigParseTestMpm02", SigParseTestMpm02);
4559
    UtRegisterTest("SigParseTestAppLayerTLS01", SigParseTestAppLayerTLS01);
4560
    UtRegisterTest("SigParseTestAppLayerTLS02", SigParseTestAppLayerTLS02);
4561
    UtRegisterTest("SigParseTestAppLayerTLS03", SigParseTestAppLayerTLS03);
4562
    UtRegisterTest("SigParseTestUnbalancedQuotes01", SigParseTestUnbalancedQuotes01);
4563
4564
    UtRegisterTest("SigParseTestContentGtDsize01",
4565
            SigParseTestContentGtDsize01);
4566
    UtRegisterTest("SigParseTestContentGtDsize02",
4567
            SigParseTestContentGtDsize02);
4568
4569
    UtRegisterTest("SigParseBidirWithSameSrcAndDest01",
4570
            SigParseBidirWithSameSrcAndDest01);
4571
    UtRegisterTest("SigParseBidirWithSameSrcAndDest02",
4572
            SigParseBidirWithSameSrcAndDest02);
4573
    UtRegisterTest("SigParseTestActionReject", SigParseTestActionReject);
4574
    UtRegisterTest("SigParseTestActionDrop", SigParseTestActionDrop);
4575
#endif /* UNITTESTS */
4576
0
}