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

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

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

70.95
/src/detect-app-layer-protocol.c
1
/* Copyright (C) 2007-2025 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17

18
/**
19
 * \file
20
 *
21
 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
22
 */
23

24
#include "suricata-common.h"
25
#include "detect-engine.h"
26
#include "detect-engine-build.h"
27
#include "detect-engine-prefilter.h"
28
#include "detect-engine-prefilter-common.h"
29
#include "detect-parse.h"
30
#include "detect-app-layer-protocol.h"
31
#include "app-layer.h"
32
#include "app-layer-parser.h"
33
#include "util-debug.h"
34
#include "util-unittest.h"
35
#include "util-unittest-helper.h"
36

37
#ifdef UNITTESTS
38
static void DetectAppLayerProtocolRegisterTests(void);
39
#endif
40

41
enum {
42
    DETECT_ALPROTO_DIRECTION = 0,
43
    DETECT_ALPROTO_FINAL = 1,
44
    DETECT_ALPROTO_EITHER = 2,
45
    DETECT_ALPROTO_TOSERVER = 3,
46
    DETECT_ALPROTO_TOCLIENT = 4,
47
    DETECT_ALPROTO_ORIG = 5,
48
};
49

50
typedef struct DetectAppLayerProtocolData_ {
51
    AppProto alproto;
52
    uint8_t negated;
53
    uint8_t mode;
54
} DetectAppLayerProtocolData;
55

56
static int DetectAppLayerProtocolPacketMatch(
57
        DetectEngineThreadCtx *det_ctx,
58
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
59
{
17,878✔
60
    SCEnter();
17,878✔
61

62
    bool r = false;
17,878✔
63
    const DetectAppLayerProtocolData *data = (const DetectAppLayerProtocolData *)ctx;
17,878✔
64

65
    /* if the sig is PD-only we only match when PD packet flags are set */
66
    if (s->type == SIG_TYPE_PDONLY &&
17,878✔
67
            (p->flags & (PKT_PROTO_DETECT_TS_DONE | PKT_PROTO_DETECT_TC_DONE)) == 0) {
17,878✔
68
        SCLogDebug("packet %" PRIu64 ": flags not set", PcapPacketCntGet(p));
16,278✔
69
        SCReturnInt(0);
16,278✔
70
    }
16,278✔
71

72
    const Flow *f = p->flow;
1,600✔
73
    if (f == NULL) {
1,600✔
74
        SCLogDebug("packet %" PRIu64 ": no flow", PcapPacketCntGet(p));
×
75
        SCReturnInt(0);
×
76
    }
×
77

78
    switch (data->mode) {
1,600✔
79
        case DETECT_ALPROTO_DIRECTION:
1,476✔
80
            if (data->negated) {
1,476✔
81
                if (p->flowflags & FLOW_PKT_TOSERVER) {
1,295✔
82
                    if (f->alproto_ts == ALPROTO_UNKNOWN)
828✔
83
                        SCReturnInt(0);
96✔
84
                    r = AppProtoEquals(data->alproto, f->alproto_ts);
732✔
85
                } else {
732✔
86
                    if (f->alproto_tc == ALPROTO_UNKNOWN)
467✔
87
                        SCReturnInt(0);
79✔
88
                    r = AppProtoEquals(data->alproto, f->alproto_tc);
388✔
89
                }
388✔
90
            } else {
1,295✔
91
                if (p->flowflags & FLOW_PKT_TOSERVER) {
181✔
92
                    r = AppProtoEquals(data->alproto, f->alproto_ts);
102✔
93
                } else {
102✔
94
                    r = AppProtoEquals(data->alproto, f->alproto_tc);
79✔
95
                }
79✔
96
            }
181✔
97
            break;
1,301✔
98
        case DETECT_ALPROTO_ORIG:
1,301✔
UNCOV
99
            if (data->negated) {
×
100
                if (f->alproto_orig == ALPROTO_UNKNOWN)
×
101
                    SCReturnInt(0);
×
102
                r = AppProtoEquals(data->alproto, f->alproto_orig);
×
UNCOV
103
            } else {
×
UNCOV
104
                r = AppProtoEquals(data->alproto, f->alproto_orig);
×
UNCOV
105
            }
×
UNCOV
106
            break;
×
107
        case DETECT_ALPROTO_FINAL:
29✔
108
            if (data->negated) {
29✔
109
                if (f->alproto == ALPROTO_UNKNOWN)
29✔
110
                    SCReturnInt(0);
×
111
                r = AppProtoEquals(data->alproto, f->alproto);
29✔
112
            } else {
29✔
UNCOV
113
                r = AppProtoEquals(data->alproto, f->alproto);
×
UNCOV
114
            }
×
115
            break;
29✔
116
        case DETECT_ALPROTO_TOSERVER:
29✔
UNCOV
117
            if (data->negated) {
×
118
                if (f->alproto_ts == ALPROTO_UNKNOWN)
×
119
                    SCReturnInt(0);
×
120
                r = AppProtoEquals(data->alproto, f->alproto_ts);
×
UNCOV
121
            } else {
×
UNCOV
122
                r = AppProtoEquals(data->alproto, f->alproto_ts);
×
UNCOV
123
            }
×
UNCOV
124
            break;
×
UNCOV
125
        case DETECT_ALPROTO_TOCLIENT:
×
UNCOV
126
            if (data->negated) {
×
127
                if (f->alproto_tc == ALPROTO_UNKNOWN)
×
128
                    SCReturnInt(0);
×
129
                r = AppProtoEquals(data->alproto, f->alproto_tc);
×
UNCOV
130
            } else {
×
UNCOV
131
                r = AppProtoEquals(data->alproto, f->alproto_tc);
×
UNCOV
132
            }
×
UNCOV
133
            break;
×
134
        case DETECT_ALPROTO_EITHER:
95✔
135
            if (data->negated) {
95✔
136
                if (f->alproto_ts == ALPROTO_UNKNOWN && f->alproto_tc == ALPROTO_UNKNOWN)
95✔
137
                    SCReturnInt(0);
65✔
138
                r = AppProtoEquals(data->alproto, f->alproto_tc) ||
30✔
139
                    AppProtoEquals(data->alproto, f->alproto_ts);
30✔
140
            } else {
30✔
141
                r = AppProtoEquals(data->alproto, f->alproto_tc) ||
×
142
                    AppProtoEquals(data->alproto, f->alproto_ts);
×
143
            }
×
144
            break;
30✔
145
    }
1,600✔
146
    r = r ^ data->negated;
1,360✔
147
    if (r) {
1,360✔
148
        SCReturnInt(1);
692✔
149
    }
692✔
150
    SCReturnInt(0);
1,360✔
151
}
1,360✔
152

153
#define MAX_ALPROTO_NAME 50
174✔
154
static DetectAppLayerProtocolData *DetectAppLayerProtocolParse(const char *arg, bool negate)
155
{
5,700✔
156
    DetectAppLayerProtocolData *data;
5,700✔
157
    AppProto alproto = ALPROTO_UNKNOWN;
5,700✔
158

159
    char alproto_copy[MAX_ALPROTO_NAME];
5,700✔
160
    char *sep = strchr(arg, ',');
5,700✔
161
    char *alproto_name;
5,700✔
162
    if (sep && sep - arg < MAX_ALPROTO_NAME) {
5,700✔
163
        strlcpy(alproto_copy, arg, sep - arg + 1);
146✔
164
        alproto_name = alproto_copy;
146✔
165
    } else {
5,554✔
166
        alproto_name = (char *)arg;
5,554✔
167
    }
5,554✔
168
    if (strcmp(alproto_name, "failed") == 0) {
5,700✔
169
        alproto = ALPROTO_FAILED;
29✔
170
    } else if (strcmp(alproto_name, "unknown") == 0) {
5,671✔
171
        if (negate) {
3✔
172
            SCLogError("app-layer-protocol "
×
173
                       "keyword can't use negation with protocol 'unknown'");
×
174
            return NULL;
×
175
        }
×
176
        alproto = ALPROTO_UNKNOWN;
3✔
177
    } else {
5,668✔
178
        alproto = AppLayerGetProtoByName(alproto_name);
5,668✔
179
        if (alproto == ALPROTO_UNKNOWN) {
5,668✔
180
            SCLogError("app-layer-protocol "
357✔
181
                       "keyword supplied with unknown protocol \"%s\"",
357✔
182
                    alproto_name);
357✔
183
            return NULL;
357✔
184
        }
357✔
185
    }
5,668✔
186
    uint8_t mode = DETECT_ALPROTO_DIRECTION;
5,343✔
187
    if (sep) {
5,343✔
188
        if (strcmp(sep + 1, "final") == 0) {
139✔
189
            mode = DETECT_ALPROTO_FINAL;
50✔
190
        } else if (strcmp(sep + 1, "original") == 0) {
89✔
191
            mode = DETECT_ALPROTO_ORIG;
8✔
192
        } else if (strcmp(sep + 1, "either") == 0) {
81✔
193
            mode = DETECT_ALPROTO_EITHER;
32✔
194
        } else if (strcmp(sep + 1, "to_server") == 0) {
49✔
195
            mode = DETECT_ALPROTO_TOSERVER;
2✔
196
        } else if (strcmp(sep + 1, "to_client") == 0) {
47✔
197
            mode = DETECT_ALPROTO_TOCLIENT;
4✔
198
        } else if (strcmp(sep + 1, "direction") == 0) {
43✔
199
            mode = DETECT_ALPROTO_DIRECTION;
3✔
200
        } else {
40✔
201
            SCLogError("app-layer-protocol "
40✔
202
                       "keyword supplied with unknown mode \"%s\"",
40✔
203
                    sep + 1);
40✔
204
            return NULL;
40✔
205
        }
40✔
206
    }
139✔
207

208
    data = SCMalloc(sizeof(DetectAppLayerProtocolData));
5,303✔
209
    if (unlikely(data == NULL))
5,303✔
210
        return NULL;
×
211
    data->alproto = alproto;
5,303✔
212
    data->negated = negate;
5,303✔
213
    data->mode = mode;
5,303✔
214

215
    return data;
5,303✔
216
}
5,303✔
217

218
static bool HasConflicts(const DetectAppLayerProtocolData *us,
219
                          const DetectAppLayerProtocolData *them)
220
{
1,082✔
221
    /* mixing negated and non negated is illegal */
222
    if ((them->negated ^ us->negated) && them->mode == us->mode)
1,082✔
223
        return true;
601✔
224
    /* multiple non-negated is illegal */
225
    if (!us->negated && them->mode == us->mode)
481✔
226
        return true;
3✔
227
    /* duplicate option */
228
    if (us->alproto == them->alproto && them->mode == us->mode)
478✔
229
        return true;
8✔
230

231
    /* all good */
232
    return false;
470✔
233
}
478✔
234

235
static int DetectAppLayerProtocolSetup(DetectEngineCtx *de_ctx,
236
        Signature *s, const char *arg)
237
{
5,732✔
238
    DetectAppLayerProtocolData *data = NULL;
5,732✔
239

240
    if (s->alproto != ALPROTO_UNKNOWN) {
5,732✔
241
        SCLogError("Either we already "
32✔
242
                   "have the rule match on an app layer protocol set through "
32✔
243
                   "other keywords that match on this protocol, or have "
32✔
244
                   "already seen a non-negated app-layer-protocol.");
32✔
245
        goto error;
32✔
246
    }
32✔
247

248
    data = DetectAppLayerProtocolParse(arg, s->init_data->negated);
5,700✔
249
    if (data == NULL)
5,700✔
250
        goto error;
397✔
251

252
    SigMatch *tsm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
5,303✔
253
    for ( ; tsm != NULL; tsm = tsm->next) {
6,652✔
254
        if (tsm->type == DETECT_APP_LAYER_PROTOCOL) {
1,961✔
255
            const DetectAppLayerProtocolData *them = (const DetectAppLayerProtocolData *)tsm->ctx;
1,082✔
256

257
            if (HasConflicts(data, them)) {
1,082✔
258
                SCLogError("can't mix "
612✔
259
                           "positive app-layer-protocol match with negated "
612✔
260
                           "match or match for 'failed'.");
612✔
261
                goto error;
612✔
262
            }
612✔
263
        }
1,082✔
264
    }
1,961✔
265

266
    if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_APP_LAYER_PROTOCOL, (SigMatchCtx *)data,
4,691✔
267
                DETECT_SM_LIST_MATCH) == NULL) {
4,691✔
268
        goto error;
×
269
    }
×
270
    return 0;
4,691✔
271

272
error:
1,041✔
273
    if (data != NULL)
1,041✔
274
        SCFree(data);
612✔
275
    return -1;
1,041✔
276
}
4,691✔
277

278
static void DetectAppLayerProtocolFree(DetectEngineCtx *de_ctx, void *ptr)
279
{
4,691✔
280
    SCFree(ptr);
4,691✔
281
}
4,691✔
282

283
/** \internal
284
 *  \brief prefilter function for protocol detect matching
285
 */
286
static void
287
PrefilterPacketAppProtoMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
288
{
293✔
289
    const PrefilterPacketHeaderCtx *ctx = pectx;
293✔
290

291
    if (!PrefilterPacketHeaderExtraMatch(ctx, p)) {
293✔
292
        SCLogDebug("packet %" PRIu64 ": extra match failed", PcapPacketCntGet(p));
×
293
        SCReturn;
×
294
    }
×
295

296
    if (p->flow == NULL) {
293✔
297
        SCLogDebug("packet %" PRIu64 ": no flow, no alproto", PcapPacketCntGet(p));
×
298
        SCReturn;
×
299
    }
×
300

301
    if ((p->flags & (PKT_PROTO_DETECT_TS_DONE|PKT_PROTO_DETECT_TC_DONE)) == 0) {
293✔
302
        SCLogDebug("packet %" PRIu64 ": flags not set", PcapPacketCntGet(p));
273✔
303
        SCReturn;
273✔
304
    }
273✔
305

306
    Flow *f = p->flow;
20✔
307
    AppProto alproto = ALPROTO_UNKNOWN;
20✔
308
    bool negated = (bool)ctx->v1.u8[2];
20✔
309
    switch (ctx->v1.u8[3]) {
20✔
310
        case DETECT_ALPROTO_DIRECTION:
20✔
311
            if (p->flowflags & FLOW_PKT_TOSERVER) {
20✔
312
                alproto = f->alproto_ts;
12✔
313
            } else {
12✔
314
                alproto = f->alproto_tc;
8✔
315
            }
8✔
316
            break;
20✔
UNCOV
317
        case DETECT_ALPROTO_ORIG:
×
UNCOV
318
            alproto = f->alproto_orig;
×
UNCOV
319
            break;
×
320
        case DETECT_ALPROTO_FINAL:
×
321
            alproto = f->alproto;
×
322
            break;
×
323
        case DETECT_ALPROTO_TOSERVER:
×
324
            alproto = f->alproto_ts;
×
325
            break;
×
326
        case DETECT_ALPROTO_TOCLIENT:
×
327
            alproto = f->alproto_tc;
×
328
            break;
×
UNCOV
329
        case DETECT_ALPROTO_EITHER:
×
330
            // check if either protocol toclient or toserver matches
331
            // the one in the signature ctx
UNCOV
332
            if (negated) {
×
UNCOV
333
                if (f->alproto_tc != ALPROTO_UNKNOWN &&
×
UNCOV
334
                        !AppProtoEquals(ctx->v1.u16[0], f->alproto_tc)) {
×
335
                    PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
×
UNCOV
336
                } else if (f->alproto_ts != ALPROTO_UNKNOWN &&
×
UNCOV
337
                           !AppProtoEquals(ctx->v1.u16[0], f->alproto_ts)) {
×
338
                    PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
×
339
                }
×
UNCOV
340
            } else {
×
341
                if (AppProtoEquals(ctx->v1.u16[0], f->alproto_tc) ||
×
342
                        AppProtoEquals(ctx->v1.u16[0], f->alproto_ts)) {
×
343
                    PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
×
344
                }
×
345
            }
×
346
            // We return right away to avoid calling PrefilterAddSids again
UNCOV
347
            return;
×
348
    }
20✔
349

350
    if (negated) {
20✔
351
        if (alproto != ALPROTO_UNKNOWN) {
20✔
352
            if (!AppProtoEquals(ctx->v1.u16[0], alproto)) {
20✔
353
                PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
19✔
354
            }
19✔
355
        }
20✔
356
    } else {
20✔
UNCOV
357
        if (AppProtoEquals(ctx->v1.u16[0], alproto)) {
×
UNCOV
358
            PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
×
UNCOV
359
        }
×
UNCOV
360
    }
×
361
}
20✔
362

363
static void
364
PrefilterPacketAppProtoSet(PrefilterPacketHeaderValue *v, void *smctx)
365
{
280✔
366
    const DetectAppLayerProtocolData *a = smctx;
280✔
367
    v->u16[0] = a->alproto;
280✔
368
    v->u8[2] = (uint8_t)a->negated;
280✔
369
    v->u8[3] = a->mode;
280✔
370
}
280✔
371

372
static bool
373
PrefilterPacketAppProtoCompare(PrefilterPacketHeaderValue v, void *smctx)
374
{
161✔
375
    const DetectAppLayerProtocolData *a = smctx;
161✔
376
    if (v.u16[0] == a->alproto && v.u8[2] == (uint8_t)a->negated && v.u8[3] == a->mode)
161✔
377
        return true;
143✔
378
    return false;
18✔
379
}
161✔
380

381
static int PrefilterSetupAppProto(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
382
{
195✔
383
    return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_APP_LAYER_PROTOCOL, SIG_MASK_REQUIRE_FLOW,
195✔
384
            PrefilterPacketAppProtoSet, PrefilterPacketAppProtoCompare,
195✔
385
            PrefilterPacketAppProtoMatch);
195✔
386
}
195✔
387

388
static bool PrefilterAppProtoIsPrefilterable(const Signature *s)
389
{
×
390
    if (s->type == SIG_TYPE_PDONLY) {
×
391
        SCLogDebug("prefilter on PD %u", s->id);
×
392
        return true;
×
393
    }
×
394
    return false;
×
395
}
×
396

397
void DetectAppLayerProtocolRegister(void)
398
{
3✔
399
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].name = "app-layer-protocol";
3✔
400
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].desc = "match on the detected app-layer protocol";
3✔
401
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].url = "/rules/app-layer.html#app-layer-protocol";
3✔
402
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Match = DetectAppLayerProtocolPacketMatch;
3✔
403
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Setup = DetectAppLayerProtocolSetup;
3✔
404
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Free = DetectAppLayerProtocolFree;
3✔
405
#ifdef UNITTESTS
406
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].RegisterTests = DetectAppLayerProtocolRegisterTests;
407
#endif
408
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].flags =
3✔
409
            (SIGMATCH_QUOTES_OPTIONAL | SIGMATCH_HANDLE_NEGATION | SIGMATCH_SUPPORT_FIREWALL);
3✔
410

411
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SetupPrefilter = PrefilterSetupAppProto;
3✔
412
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SupportsPrefilter = PrefilterAppProtoIsPrefilterable;
3✔
413
}
3✔
414

415
/**********************************Unittests***********************************/
416

417
#ifdef UNITTESTS
418

419
static int DetectAppLayerProtocolTest01(void)
420
{
421
    DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", false);
422
    FAIL_IF_NULL(data);
423
    FAIL_IF(data->alproto != ALPROTO_HTTP);
424
    FAIL_IF(data->negated != 0);
425
    DetectAppLayerProtocolFree(NULL, data);
426
    PASS;
427
}
428

429
static int DetectAppLayerProtocolTest02(void)
430
{
431
    DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", true);
432
    FAIL_IF_NULL(data);
433
    FAIL_IF(data->alproto != ALPROTO_HTTP);
434
    FAIL_IF(data->negated == 0);
435
    DetectAppLayerProtocolFree(NULL, data);
436
    PASS;
437
}
438

439
static int DetectAppLayerProtocolTest03(void)
440
{
441
    Signature *s = NULL;
442
    DetectAppLayerProtocolData *data = NULL;
443
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
444
    FAIL_IF_NULL(de_ctx);
445
    de_ctx->flags |= DE_QUIET;
446

447
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
448
            "(app-layer-protocol:http; sid:1;)");
449
    FAIL_IF_NULL(s);
450

451
    FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
452

453
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
454
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
455

456
    data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
457
    FAIL_IF(data->alproto != ALPROTO_HTTP);
458
    FAIL_IF(data->negated);
459
    DetectEngineCtxFree(de_ctx);
460
    PASS;
461
}
462

463
static int DetectAppLayerProtocolTest04(void)
464
{
465
    Signature *s = NULL;
466
    DetectAppLayerProtocolData *data = NULL;
467
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
468
    FAIL_IF_NULL(de_ctx);
469
    de_ctx->flags |= DE_QUIET;
470

471
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
472
            "(app-layer-protocol:!http; sid:1;)");
473
    FAIL_IF_NULL(s);
474
    FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
475
    FAIL_IF(s->flags & SIG_FLAG_APPLAYER);
476

477
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
478
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
479

480
    data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
481
    FAIL_IF_NULL(data);
482
    FAIL_IF(data->alproto != ALPROTO_HTTP);
483
    FAIL_IF(data->negated == 0);
484

485
    DetectEngineCtxFree(de_ctx);
486
    PASS;
487
}
488

489
static int DetectAppLayerProtocolTest05(void)
490
{
491
    Signature *s = NULL;
492
    DetectAppLayerProtocolData *data = NULL;
493
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
494
    FAIL_IF_NULL(de_ctx);
495
    de_ctx->flags |= DE_QUIET;
496

497
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
498
            "(app-layer-protocol:!http; app-layer-protocol:!smtp; sid:1;)");
499
    FAIL_IF_NULL(s);
500
    FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
501
    FAIL_IF(s->flags & SIG_FLAG_APPLAYER);
502

503
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
504
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
505

506
    data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
507
    FAIL_IF_NULL(data);
508
    FAIL_IF(data->alproto != ALPROTO_HTTP);
509
    FAIL_IF(data->negated == 0);
510

511
    data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->next->ctx;
512
    FAIL_IF_NULL(data);
513
    FAIL_IF(data->alproto != ALPROTO_SMTP);
514
    FAIL_IF(data->negated == 0);
515

516
    DetectEngineCtxFree(de_ctx);
517
    PASS;
518
}
519

520
static int DetectAppLayerProtocolTest06(void)
521
{
522
    Signature *s = NULL;
523
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
524
    FAIL_IF_NULL(de_ctx);
525
    de_ctx->flags |= DE_QUIET;
526

527
    s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
528
            "(app-layer-protocol:smtp; sid:1;)");
529
    FAIL_IF_NOT_NULL(s);
530
    DetectEngineCtxFree(de_ctx);
531
    PASS;
532
}
533

534
static int DetectAppLayerProtocolTest07(void)
535
{
536
    Signature *s = NULL;
537
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
538
    FAIL_IF_NULL(de_ctx);
539
    de_ctx->flags |= DE_QUIET;
540

541
    s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
542
            "(app-layer-protocol:!smtp; sid:1;)");
543
    FAIL_IF_NOT_NULL(s);
544
    DetectEngineCtxFree(de_ctx);
545
    PASS;
546
}
547

548
static int DetectAppLayerProtocolTest08(void)
549
{
550
    Signature *s = NULL;
551
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
552
    FAIL_IF_NULL(de_ctx);
553
    de_ctx->flags |= DE_QUIET;
554

555
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
556
            "(app-layer-protocol:!smtp; app-layer-protocol:http; sid:1;)");
557
    FAIL_IF_NOT_NULL(s);
558
    DetectEngineCtxFree(de_ctx);
559
    PASS;
560
}
561

562
static int DetectAppLayerProtocolTest09(void)
563
{
564
    Signature *s = NULL;
565
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
566
    FAIL_IF_NULL(de_ctx);
567
    de_ctx->flags |= DE_QUIET;
568

569
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
570
            "(app-layer-protocol:http; app-layer-protocol:!smtp; sid:1;)");
571
    FAIL_IF_NOT_NULL(s);
572
    DetectEngineCtxFree(de_ctx);
573
    PASS;
574
}
575

576
static int DetectAppLayerProtocolTest10(void)
577
{
578
    Signature *s = NULL;
579
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
580
    FAIL_IF_NULL(de_ctx);
581
    de_ctx->flags |= DE_QUIET;
582

583
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
584
            "(app-layer-protocol:smtp; app-layer-protocol:!http; sid:1;)");
585
    FAIL_IF_NOT_NULL(s);
586
    DetectEngineCtxFree(de_ctx);
587
    PASS;
588
}
589

590
static int DetectAppLayerProtocolTest11(void)
591
{
592
    DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", false);
593
    FAIL_IF_NULL(data);
594
    FAIL_IF(data->alproto != ALPROTO_FAILED);
595
    FAIL_IF(data->negated != 0);
596
    DetectAppLayerProtocolFree(NULL, data);
597
    PASS;
598
}
599

600
static int DetectAppLayerProtocolTest12(void)
601
{
602
    DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", true);
603
    FAIL_IF_NULL(data);
604
    FAIL_IF(data->alproto != ALPROTO_FAILED);
605
    FAIL_IF(data->negated == 0);
606
    DetectAppLayerProtocolFree(NULL, data);
607
    PASS;
608
}
609

610
static int DetectAppLayerProtocolTest13(void)
611
{
612
    Signature *s = NULL;
613
    DetectAppLayerProtocolData *data = NULL;
614
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
615
    FAIL_IF_NULL(de_ctx);
616
    de_ctx->flags |= DE_QUIET;
617

618
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
619
            "(app-layer-protocol:failed; sid:1;)");
620
    FAIL_IF_NULL(s);
621

622
    FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
623

624
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
625
    FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
626

627
    data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
628
    FAIL_IF(data->alproto != ALPROTO_FAILED);
629
    FAIL_IF(data->negated);
630
    DetectEngineCtxFree(de_ctx);
631
    PASS;
632
}
633

634
static int DetectAppLayerProtocolTest14(void)
635
{
636
    DetectAppLayerProtocolData *data = NULL;
637
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
638
    FAIL_IF_NULL(de_ctx);
639
    de_ctx->flags |= DE_QUIET;
640

641
    Signature *s1 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
642
            "(app-layer-protocol:http; flowbits:set,blah; sid:1;)");
643
    FAIL_IF_NULL(s1);
644
    FAIL_IF(s1->alproto != ALPROTO_UNKNOWN);
645
    FAIL_IF_NULL(s1->init_data->smlists[DETECT_SM_LIST_MATCH]);
646
    FAIL_IF_NULL(s1->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
647
    data = (DetectAppLayerProtocolData *)s1->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
648
    FAIL_IF(data->alproto != ALPROTO_HTTP);
649
    FAIL_IF(data->negated);
650

651
    Signature *s2 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
652
            "(app-layer-protocol:http; flow:to_client; sid:2;)");
653
    FAIL_IF_NULL(s2);
654
    FAIL_IF(s2->alproto != ALPROTO_UNKNOWN);
655
    FAIL_IF_NULL(s2->init_data->smlists[DETECT_SM_LIST_MATCH]);
656
    FAIL_IF_NULL(s2->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
657
    data = (DetectAppLayerProtocolData *)s2->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
658
    FAIL_IF(data->alproto != ALPROTO_HTTP);
659
    FAIL_IF(data->negated);
660

661
    /* flow:established and other options not supported for PD-only */
662
    Signature *s3 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
663
            "(app-layer-protocol:http; flow:to_client,established; sid:3;)");
664
    FAIL_IF_NULL(s3);
665
    FAIL_IF(s3->alproto != ALPROTO_UNKNOWN);
666
    FAIL_IF_NULL(s3->init_data->smlists[DETECT_SM_LIST_MATCH]);
667
    FAIL_IF_NULL(s3->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
668
    data = (DetectAppLayerProtocolData *)s3->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
669
    FAIL_IF(data->alproto != ALPROTO_HTTP);
670
    FAIL_IF(data->negated);
671

672
    SigGroupBuild(de_ctx);
673
    FAIL_IF_NOT(s1->type == SIG_TYPE_PDONLY);
674
    FAIL_IF_NOT(s2->type == SIG_TYPE_PDONLY);
675
    FAIL_IF(s3->type == SIG_TYPE_PDONLY); // failure now
676

677
    DetectEngineCtxFree(de_ctx);
678
    PASS;
679
}
680

681

682
static void DetectAppLayerProtocolRegisterTests(void)
683
{
684
    UtRegisterTest("DetectAppLayerProtocolTest01",
685
                   DetectAppLayerProtocolTest01);
686
    UtRegisterTest("DetectAppLayerProtocolTest02",
687
                   DetectAppLayerProtocolTest02);
688
    UtRegisterTest("DetectAppLayerProtocolTest03",
689
                   DetectAppLayerProtocolTest03);
690
    UtRegisterTest("DetectAppLayerProtocolTest04",
691
                   DetectAppLayerProtocolTest04);
692
    UtRegisterTest("DetectAppLayerProtocolTest05",
693
                   DetectAppLayerProtocolTest05);
694
    UtRegisterTest("DetectAppLayerProtocolTest06",
695
                   DetectAppLayerProtocolTest06);
696
    UtRegisterTest("DetectAppLayerProtocolTest07",
697
                   DetectAppLayerProtocolTest07);
698
    UtRegisterTest("DetectAppLayerProtocolTest08",
699
                   DetectAppLayerProtocolTest08);
700
    UtRegisterTest("DetectAppLayerProtocolTest09",
701
                   DetectAppLayerProtocolTest09);
702
    UtRegisterTest("DetectAppLayerProtocolTest10",
703
                   DetectAppLayerProtocolTest10);
704
    UtRegisterTest("DetectAppLayerProtocolTest11",
705
                   DetectAppLayerProtocolTest11);
706
    UtRegisterTest("DetectAppLayerProtocolTest12",
707
                   DetectAppLayerProtocolTest12);
708
    UtRegisterTest("DetectAppLayerProtocolTest13",
709
                   DetectAppLayerProtocolTest13);
710
    UtRegisterTest("DetectAppLayerProtocolTest14",
711
                   DetectAppLayerProtocolTest14);
712
}
713
#endif /* UNITTESTS */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc