Coverage Report

Created: 2025-07-23 07:29

/src/suricata7/src/detect-isdataat.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2007-2020 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 Pablo Rincon <pablo.rincon.crespo@gmail.com>
22
 *
23
 * Implements isdataat keyword
24
 */
25
26
#include "suricata-common.h"
27
#include "decode.h"
28
#include "detect.h"
29
#include "detect-engine.h"
30
#include "detect-parse.h"
31
#include "app-layer.h"
32
33
#include "util-unittest.h"
34
#include "util-unittest-helper.h"
35
36
#include "detect-isdataat.h"
37
#include "detect-content.h"
38
#include "detect-uricontent.h"
39
#include "detect-engine-build.h"
40
41
#include "flow.h"
42
#include "flow-var.h"
43
44
#include "util-debug.h"
45
#include "util-byte.h"
46
#include "detect-pcre.h"
47
#include "detect-byte.h"
48
49
/**
50
 * \brief Regex for parsing our isdataat options
51
 */
52
73
#define PARSE_REGEX  "^\\s*!?([^\\s,]+)\\s*(,\\s*relative)?\\s*(,\\s*rawbytes\\s*)?\\s*$"
53
54
static DetectParseRegex parse_regex;
55
56
int DetectIsdataatSetup (DetectEngineCtx *, Signature *, const char *);
57
#ifdef UNITTESTS
58
static void DetectIsdataatRegisterTests(void);
59
#endif
60
void DetectIsdataatFree(DetectEngineCtx *, void *);
61
62
static int DetectEndsWithSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr);
63
64
/**
65
 * \brief Registration function for isdataat: keyword
66
 */
67
void DetectIsdataatRegister(void)
68
73
{
69
73
    sigmatch_table[DETECT_ISDATAAT].name = "isdataat";
70
73
    sigmatch_table[DETECT_ISDATAAT].desc = "check if there is still data at a specific part of the payload";
71
73
    sigmatch_table[DETECT_ISDATAAT].url = "/rules/payload-keywords.html#isdataat";
72
    /* match is handled in DetectEngineContentInspection() */
73
73
    sigmatch_table[DETECT_ISDATAAT].Match = NULL;
74
73
    sigmatch_table[DETECT_ISDATAAT].Setup = DetectIsdataatSetup;
75
73
    sigmatch_table[DETECT_ISDATAAT].Free  = DetectIsdataatFree;
76
#ifdef UNITTESTS
77
    sigmatch_table[DETECT_ISDATAAT].RegisterTests = DetectIsdataatRegisterTests;
78
#endif
79
73
    sigmatch_table[DETECT_ENDS_WITH].name = "endswith";
80
73
    sigmatch_table[DETECT_ENDS_WITH].desc = "make sure the previous content matches exactly at the end of the buffer";
81
73
    sigmatch_table[DETECT_ENDS_WITH].url = "/rules/payload-keywords.html#endswith";
82
73
    sigmatch_table[DETECT_ENDS_WITH].Setup = DetectEndsWithSetup;
83
73
    sigmatch_table[DETECT_ENDS_WITH].flags = SIGMATCH_NOOPT;
84
85
73
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
86
73
}
87
88
/**
89
 * \brief This function is used to parse isdataat options passed via isdataat: keyword
90
 *
91
 * \param de_ctx Pointer to the detection engine context
92
 * \param isdataatstr Pointer to the user provided isdataat options
93
 *
94
 * \retval idad pointer to DetectIsdataatData on success
95
 * \retval NULL on failure
96
 */
97
static DetectIsdataatData *DetectIsdataatParse (DetectEngineCtx *de_ctx, const char *isdataatstr, char **offset)
98
12.5k
{
99
12.5k
    DetectIsdataatData *idad = NULL;
100
12.5k
    char *args[3] = {NULL,NULL,NULL};
101
12.5k
    int res = 0;
102
12.5k
    size_t pcre2_len;
103
12.5k
    int i=0;
104
105
12.5k
    pcre2_match_data *match = NULL;
106
12.5k
    int ret = DetectParsePcreExec(&parse_regex, &match, isdataatstr, 0, 0);
107
12.5k
    if (ret < 1 || ret > 4) {
108
1.42k
        SCLogError("pcre_exec parse error, ret %" PRId32 ", string %s", ret, isdataatstr);
109
1.42k
        goto error;
110
1.42k
    }
111
112
11.1k
    if (ret > 1) {
113
11.1k
        const char *str_ptr;
114
11.1k
        res = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
115
11.1k
        if (res < 0) {
116
0
            SCLogError("pcre2_substring_get_bynumber failed");
117
0
            goto error;
118
0
        }
119
11.1k
        args[0] = (char *)str_ptr;
120
121
122
11.1k
        if (ret > 2) {
123
8.19k
            res = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
124
8.19k
            if (res < 0) {
125
2
                SCLogError("pcre2_substring_get_bynumber failed");
126
2
                goto error;
127
2
            }
128
8.19k
            args[1] = (char *)str_ptr;
129
8.19k
        }
130
11.1k
        if (ret > 3) {
131
0
            res = pcre2_substring_get_bynumber(match, 3, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
132
0
            if (res < 0) {
133
0
                SCLogError("pcre2_substring_get_bynumber failed");
134
0
                goto error;
135
0
            }
136
0
            args[2] = (char *)str_ptr;
137
0
        }
138
139
11.1k
        idad = SCMalloc(sizeof(DetectIsdataatData));
140
11.1k
        if (unlikely(idad == NULL))
141
0
            goto error;
142
143
11.1k
        idad->flags = 0;
144
11.1k
        idad->dataat = 0;
145
146
11.1k
        if (args[0][0] != '-' && isalpha((unsigned char)args[0][0])) {
147
878
            if (offset == NULL) {
148
0
                SCLogError("isdataat supplied with "
149
0
                           "var name for offset.  \"offset\" argument supplied to "
150
0
                           "this function has to be non-NULL");
151
0
                goto error;
152
0
            }
153
878
            *offset = SCStrdup(args[0]);
154
878
            if (*offset == NULL)
155
0
                goto error;
156
10.2k
        } else {
157
10.2k
            if (StringParseUint16(&idad->dataat, 10,
158
10.2k
                                        strlen(args[0]), args[0]) < 0 ) {
159
755
                SCLogError("isdataat out of range");
160
755
                SCFree(idad);
161
755
                idad = NULL;
162
755
                goto error;
163
755
            }
164
10.2k
        }
165
166
10.3k
        if (args[1] !=NULL) {
167
8.11k
            idad->flags |= ISDATAAT_RELATIVE;
168
169
8.11k
            if(args[2] !=NULL)
170
0
                idad->flags |= ISDATAAT_RAWBYTES;
171
8.11k
        }
172
173
10.3k
        if (isdataatstr[0] == '!') {
174
2.49k
            idad->flags |= ISDATAAT_NEGATED;
175
2.49k
        }
176
177
28.8k
        for (i = 0; i < (ret -1); i++) {
178
18.4k
            if (args[i] != NULL)
179
18.4k
                pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
180
18.4k
        }
181
182
10.3k
        pcre2_match_data_free(match);
183
10.3k
        return idad;
184
185
11.1k
    }
186
187
2.18k
error:
188
2.18k
    if (match) {
189
2.18k
        pcre2_match_data_free(match);
190
2.18k
    }
191
3.02k
    for (i = 0; i < (ret -1) && i < 3; i++){
192
841
        if (args[i] != NULL)
193
837
            pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
194
841
    }
195
196
2.18k
    if (idad != NULL)
197
0
        DetectIsdataatFree(de_ctx, idad);
198
2.18k
    return NULL;
199
200
11.1k
}
201
202
/**
203
 * \brief This function is used to add the parsed isdataatdata into the current
204
 *        signature.
205
 * \param de_ctx pointer to the Detection Engine Context
206
 * \param s pointer to the Current Signature
207
 * \param isdataatstr pointer to the user provided isdataat options
208
 *
209
 * \retval 0 on Success
210
 * \retval -1 on Failure
211
 */
212
int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, const char *isdataatstr)
213
12.5k
{
214
12.5k
    SigMatch *sm = NULL;
215
12.5k
    SigMatch *prev_pm = NULL;
216
12.5k
    DetectIsdataatData *idad = NULL;
217
12.5k
    char *offset = NULL;
218
12.5k
    int ret = -1;
219
220
12.5k
    idad = DetectIsdataatParse(de_ctx, isdataatstr, &offset);
221
12.5k
    if (idad == NULL)
222
2.18k
        return -1;
223
224
10.3k
    int sm_list;
225
10.3k
    if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
226
2.58k
        if (DetectBufferGetActiveList(de_ctx, s) == -1)
227
2
            goto end;
228
2.58k
        sm_list = s->init_data->list;
229
230
2.58k
        if (idad->flags & ISDATAAT_RELATIVE) {
231
1.66k
            prev_pm = DetectGetLastSMFromLists(s, DETECT_CONTENT, DETECT_PCRE, -1);
232
1.66k
        }
233
7.78k
    } else if (idad->flags & ISDATAAT_RELATIVE) {
234
6.45k
        prev_pm = DetectGetLastSMFromLists(s,
235
6.45k
            DETECT_CONTENT, DETECT_PCRE,
236
6.45k
            DETECT_BYTETEST, DETECT_BYTEJUMP, DETECT_BYTE_EXTRACT,
237
6.45k
            DETECT_ISDATAAT, DETECT_BYTEMATH, -1);
238
6.45k
        if (prev_pm == NULL)
239
137
            sm_list = DETECT_SM_LIST_PMATCH;
240
6.31k
        else {
241
6.31k
            sm_list = SigMatchListSMBelongsTo(s, prev_pm);
242
6.31k
            if (sm_list < 0)
243
0
                goto end;
244
6.31k
        }
245
6.45k
    } else {
246
1.33k
        sm_list = DETECT_SM_LIST_PMATCH;
247
1.33k
    }
248
249
10.3k
    if (offset != NULL) {
250
878
        DetectByteIndexType index;
251
878
        if (!DetectByteRetrieveSMVar(offset, s, &index)) {
252
464
            SCLogError("Unknown byte_extract var "
253
464
                       "seen in isdataat - %s\n",
254
464
                    offset);
255
464
            goto end;
256
464
        }
257
414
        idad->dataat = index;
258
414
        idad->flags |= ISDATAAT_OFFSET_VAR;
259
414
        SCLogDebug("isdataat uses byte_extract with local id %u", idad->dataat);
260
414
        SCFree(offset);
261
414
        offset = NULL;
262
414
    }
263
264
    /* 'ends with' scenario */
265
9.90k
    if (prev_pm != NULL && prev_pm->type == DETECT_CONTENT &&
266
9.90k
        idad->dataat == 1 &&
267
9.90k
        (idad->flags & (ISDATAAT_RELATIVE|ISDATAAT_NEGATED)) == (ISDATAAT_RELATIVE|ISDATAAT_NEGATED))
268
419
    {
269
419
        DetectIsdataatFree(de_ctx, idad);
270
419
        DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
271
419
        cd->flags |= DETECT_CONTENT_ENDS_WITH;
272
419
        ret = 0;
273
419
        goto end;
274
419
    }
275
276
9.48k
    sm = SigMatchAlloc();
277
9.48k
    if (sm == NULL)
278
0
        goto end;
279
9.48k
    sm->type = DETECT_ISDATAAT;
280
9.48k
    sm->ctx = (SigMatchCtx *)idad;
281
9.48k
    SigMatchAppendSMToList(s, sm, sm_list);
282
283
9.48k
    if (!(idad->flags & ISDATAAT_RELATIVE)) {
284
1.79k
        ret = 0;
285
1.79k
        goto end;
286
1.79k
    }
287
288
7.68k
    if (prev_pm == NULL) {
289
638
        ret = 0;
290
638
        goto end;
291
638
    }
292
293
7.05k
    if (prev_pm->type == DETECT_CONTENT) {
294
4.31k
        DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
295
4.31k
        cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
296
4.31k
    } else if (prev_pm->type == DETECT_PCRE) {
297
644
        DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx;
298
644
        pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
299
644
    }
300
301
7.05k
    ret = 0;
302
303
10.3k
end:
304
10.3k
    if (offset)
305
464
        SCFree(offset);
306
10.3k
    if (ret != 0)
307
466
        DetectIsdataatFree(de_ctx, idad);
308
10.3k
    return ret;
309
7.05k
}
310
311
/**
312
 * \brief this function will free memory associated with DetectIsdataatData
313
 *
314
 * \param idad pointer to DetectIsdataatData
315
 */
316
void DetectIsdataatFree(DetectEngineCtx *de_ctx, void *ptr)
317
10.3k
{
318
10.3k
    DetectIsdataatData *idad = (DetectIsdataatData *)ptr;
319
10.3k
    SCFree(idad);
320
10.3k
}
321
322
static int DetectEndsWithSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr)
323
39.9k
{
324
39.9k
    SigMatch *pm = NULL;
325
39.9k
    int ret = -1;
326
327
    /* retrieve the sm to apply the depth against */
328
39.9k
    pm = DetectGetLastSMFromLists(s, DETECT_CONTENT, -1);
329
39.9k
    if (pm == NULL) {
330
681
        SCLogError("endswith needs a "
331
681
                   "preceding content option");
332
681
        goto end;
333
681
    }
334
335
    /* verify other conditions. */
336
39.3k
    DetectContentData *cd = (DetectContentData *)pm->ctx;
337
338
39.3k
    cd->flags |= DETECT_CONTENT_ENDS_WITH;
339
340
39.3k
    ret = 0;
341
39.9k
 end:
342
39.9k
    return ret;
343
39.3k
}
344
345
#ifdef UNITTESTS
346
static int g_dce_stub_data_buffer_id = 0;
347
348
/**
349
 * \test DetectIsdataatTestParse01 is a test to make sure that we return a correct IsdataatData structure
350
 *  when given valid isdataat opt
351
 */
352
static int DetectIsdataatTestParse01 (void)
353
{
354
    int result = 0;
355
    DetectIsdataatData *idad = NULL;
356
    idad = DetectIsdataatParse(NULL, "30 ", NULL);
357
    if (idad != NULL) {
358
        DetectIsdataatFree(NULL, idad);
359
        result = 1;
360
    }
361
362
    return result;
363
}
364
365
/**
366
 * \test DetectIsdataatTestParse02 is a test to make sure that we return a correct IsdataatData structure
367
 *  when given valid isdataat opt
368
 */
369
static int DetectIsdataatTestParse02 (void)
370
{
371
    int result = 0;
372
    DetectIsdataatData *idad = NULL;
373
    idad = DetectIsdataatParse(NULL, "30 , relative", NULL);
374
    if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && !(idad->flags & ISDATAAT_RAWBYTES)) {
375
        DetectIsdataatFree(NULL, idad);
376
        result = 1;
377
    }
378
379
    return result;
380
}
381
382
/**
383
 * \test DetectIsdataatTestParse03 is a test to make sure that we return a correct IsdataatData structure
384
 *  when given valid isdataat opt
385
 */
386
static int DetectIsdataatTestParse03 (void)
387
{
388
    int result = 0;
389
    DetectIsdataatData *idad = NULL;
390
    idad = DetectIsdataatParse(NULL, "30,relative, rawbytes ", NULL);
391
    if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && idad->flags & ISDATAAT_RAWBYTES) {
392
        DetectIsdataatFree(NULL, idad);
393
        result = 1;
394
    }
395
396
    return result;
397
}
398
399
/**
400
 * \test Test isdataat option for dce sig.
401
 */
402
static int DetectIsdataatTestParse04(void)
403
{
404
    Signature *s = SigAlloc();
405
    FAIL_IF_NULL(s);
406
407
    FAIL_IF(DetectSignatureSetAppProto(s, ALPROTO_DCERPC) < 0);
408
409
    FAIL_IF_NOT(DetectIsdataatSetup(NULL, s, "30") == 0);
410
    SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
411
    FAIL_IF_NOT_NULL(sm);
412
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_PMATCH]);
413
    SigFree(NULL, s);
414
415
    s = SigAlloc();
416
    FAIL_IF_NULL(s);
417
    FAIL_IF(DetectSignatureSetAppProto(s, ALPROTO_DCERPC) < 0);
418
    /* relative w/o preceeding match defaults to "pmatch" */
419
    FAIL_IF_NOT(DetectIsdataatSetup(NULL, s, "30,relative") == 0);
420
    sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
421
    FAIL_IF_NOT_NULL(sm);
422
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_PMATCH]);
423
424
    SigFree(NULL, s);
425
    PASS;
426
}
427
428
static int DetectIsdataatTestParse06(void)
429
{
430
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
431
    FAIL_IF(de_ctx == NULL);
432
    de_ctx->flags |= DE_QUIET;
433
434
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
435
                               "(msg:\"Testing bytejump_body\"; "
436
                               "content:\"one\"; "
437
                               "isdataat:!4,relative; sid:1;)");
438
    FAIL_IF(s == NULL);
439
440
    FAIL_IF(s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH] == NULL);
441
442
    FAIL_IF_NOT(s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]->type == DETECT_ISDATAAT);
443
    DetectIsdataatData *data =
444
            (DetectIsdataatData *)s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]->ctx;
445
446
    FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
447
    FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
448
    FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
449
450
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
451
                               "(msg:\"Testing bytejump_body\"; "
452
                               "content:\"one\"; "
453
                               "isdataat: !4,relative; sid:2;)");
454
    FAIL_IF(s == NULL);
455
456
    FAIL_IF(s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH] == NULL);
457
458
    FAIL_IF_NOT(s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]->type == DETECT_ISDATAAT);
459
    data = (DetectIsdataatData *)s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]->ctx;
460
461
    FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
462
    FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
463
    FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
464
    DetectEngineCtxFree(de_ctx);
465
466
    PASS;
467
}
468
469
/**
470
 * \test DetectIsdataatTestPacket01 is a test to check matches of
471
 * isdataat, and isdataat relative
472
 */
473
static int DetectIsdataatTestPacket01 (void)
474
{
475
    int result = 0;
476
    uint8_t *buf = (uint8_t *)"Hi all!";
477
    uint16_t buflen = strlen((char *)buf);
478
    Packet *p[3];
479
    p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
480
    p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_UDP);
481
    p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
482
483
    if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
484
        goto end;
485
486
    const char *sigs[5];
487
    sigs[0]= "alert ip any any -> any any (msg:\"Testing window 1\"; isdataat:6; sid:1;)";
488
    sigs[1]= "alert ip any any -> any any (msg:\"Testing window 2\"; content:\"all\"; isdataat:1, relative; isdataat:6; sid:2;)";
489
    sigs[2]= "alert ip any any -> any any (msg:\"Testing window 3\"; isdataat:8; sid:3;)";
490
    sigs[3]= "alert ip any any -> any any (msg:\"Testing window 4\"; content:\"Hi\"; isdataat:5, relative; sid:4;)";
491
    sigs[4]= "alert ip any any -> any any (msg:\"Testing window 4\"; content:\"Hi\"; isdataat:6, relative; sid:5;)";
492
493
    uint32_t sid[5] = {1, 2, 3, 4, 5};
494
495
    uint32_t results[3][5] = {
496
                              /* packet 0 match sid 1 but should not match sid 2 */
497
                              {1, 1, 0, 1, 0},
498
                              /* packet 1 should not match */
499
                              {1, 1, 0, 1, 0},
500
                              /* packet 2 should not match */
501
                              {1, 1, 0, 1, 0} };
502
503
    result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 5);
504
505
    UTHFreePackets(p, 3);
506
end:
507
    return result;
508
}
509
510
/**
511
 * \test DetectIsdataatTestPacket02 is a test to check matches of
512
 * isdataat, and isdataat relative works if the previous keyword is pcre
513
 * (bug 144)
514
 */
515
static int DetectIsdataatTestPacket02 (void)
516
{
517
    int result = 0;
518
    uint8_t *buf = (uint8_t *)"GET /AllWorkAndNoPlayMakesWillADullBoy HTTP/1.0"
519
                    "User-Agent: Wget/1.11.4"
520
                    "Accept: */*"
521
                    "Host: www.google.com"
522
                    "Connection: Keep-Alive"
523
                    "Date: Mon, 04 Jan 2010 17:29:39 GMT";
524
    uint16_t buflen = strlen((char *)buf);
525
    Packet *p;
526
    p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
527
528
    if (p == NULL)
529
        goto end;
530
531
    char sig[] = "alert tcp any any -> any any (msg:\"pcre with"
532
            " isdataat + relative\"; pcre:\"/A(ll|pp)WorkAndNoPlayMakesWillA"
533
            "DullBoy/\"; isdataat:96,relative; sid:1;)";
534
535
    result = UTHPacketMatchSig(p, sig);
536
537
    UTHFreePacket(p);
538
end:
539
    return result;
540
}
541
542
/**
543
 * \test DetectIsdataatTestPacket03 is a test to check matches of
544
 * isdataat, and isdataat relative works if the previous keyword is byte_jump
545
 * (bug 146)
546
 */
547
static int DetectIsdataatTestPacket03 (void)
548
{
549
    int result = 0;
550
    uint8_t *buf = (uint8_t *)"GET /AllWorkAndNoPlayMakesWillADullBoy HTTP/1.0"
551
                    "User-Agent: Wget/1.11.4"
552
                    "Accept: */*"
553
                    "Host: www.google.com"
554
                    "Connection: Keep-Alive"
555
                    "Date: Mon, 04 Jan 2010 17:29:39 GMT";
556
    uint16_t buflen = strlen((char *)buf);
557
    Packet *p;
558
    p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
559
560
    if (p == NULL)
561
        goto end;
562
563
    char sig[] = "alert tcp any any -> any any (msg:\"byte_jump match = 0 "
564
    "with distance content HTTP/1. relative against HTTP/1.0\"; byte_jump:1,"
565
    "46,string,dec; isdataat:87,relative; sid:109; rev:1;)";
566
567
    result = UTHPacketMatchSig(p, sig);
568
569
    UTHFreePacket(p);
570
end:
571
    return result;
572
}
573
574
/**
575
 * \brief this function registers unit tests for DetectIsdataat
576
 */
577
void DetectIsdataatRegisterTests(void)
578
{
579
    g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
580
581
    UtRegisterTest("DetectIsdataatTestParse01", DetectIsdataatTestParse01);
582
    UtRegisterTest("DetectIsdataatTestParse02", DetectIsdataatTestParse02);
583
    UtRegisterTest("DetectIsdataatTestParse03", DetectIsdataatTestParse03);
584
    UtRegisterTest("DetectIsdataatTestParse04", DetectIsdataatTestParse04);
585
    UtRegisterTest("DetectIsdataatTestParse06", DetectIsdataatTestParse06);
586
587
    UtRegisterTest("DetectIsdataatTestPacket01", DetectIsdataatTestPacket01);
588
    UtRegisterTest("DetectIsdataatTestPacket02", DetectIsdataatTestPacket02);
589
    UtRegisterTest("DetectIsdataatTestPacket03", DetectIsdataatTestPacket03);
590
}
591
#endif