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

OISF / suricata / 22618661228

02 Mar 2026 09:33PM UTC coverage: 42.258% (-34.4%) from 76.611%
22618661228

push

github

victorjulien
github-actions: bump actions/download-artifact from 7.0.0 to 8.0.0

Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7.0.0 to 8.0.0.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/37930b1c2...70fc10c6e)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

91511 of 216553 relevant lines covered (42.26%)

3416852.41 hits per line

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

17.91
/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
{
×
60
    SCEnter();
×
61

62
    bool r = false;
×
63
    const DetectAppLayerProtocolData *data = (const DetectAppLayerProtocolData *)ctx;
×
64

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

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

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

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

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

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

215
    return data;
1✔
216
}
1✔
217

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

231
    /* all good */
232
    return false;
×
233
}
×
234

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

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

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

252
    SigMatch *tsm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
1✔
253
    for ( ; tsm != NULL; tsm = tsm->next) {
2✔
254
        if (tsm->type == DETECT_APP_LAYER_PROTOCOL) {
1✔
255
            const DetectAppLayerProtocolData *them = (const DetectAppLayerProtocolData *)tsm->ctx;
×
256

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

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

272
error:
×
273
    if (data != NULL)
×
274
        SCFree(data);
×
275
    return -1;
×
276
}
1✔
277

278
static void DetectAppLayerProtocolFree(DetectEngineCtx *de_ctx, void *ptr)
279
{
1✔
280
    SCFree(ptr);
1✔
281
}
1✔
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
{
×
289
    const PrefilterPacketHeaderCtx *ctx = pectx;
×
290

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

296
    if (p->flow == NULL) {
×
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) {
×
302
        SCLogDebug("packet %" PRIu64 ": flags not set", PcapPacketCntGet(p));
×
303
        SCReturn;
×
304
    }
×
305

306
    Flow *f = p->flow;
×
307
    AppProto alproto = ALPROTO_UNKNOWN;
×
308
    bool negated = (bool)ctx->v1.u8[2];
×
309
    switch (ctx->v1.u8[3]) {
×
310
        case DETECT_ALPROTO_DIRECTION:
×
311
            if (p->flowflags & FLOW_PKT_TOSERVER) {
×
312
                alproto = f->alproto_ts;
×
313
            } else {
×
314
                alproto = f->alproto_tc;
×
315
            }
×
316
            break;
×
317
        case DETECT_ALPROTO_ORIG:
×
318
            alproto = f->alproto_orig;
×
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;
×
329
        case DETECT_ALPROTO_EITHER:
×
330
            // check if either protocol toclient or toserver matches
331
            // the one in the signature ctx
332
            if (negated) {
×
333
                if (f->alproto_tc != ALPROTO_UNKNOWN &&
×
334
                        !AppProtoEquals(ctx->v1.u16[0], f->alproto_tc)) {
×
335
                    PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
×
336
                } else if (f->alproto_ts != ALPROTO_UNKNOWN &&
×
337
                           !AppProtoEquals(ctx->v1.u16[0], f->alproto_ts)) {
×
338
                    PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
×
339
                }
×
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
347
            return;
×
348
    }
×
349

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

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

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

381
static int PrefilterSetupAppProto(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
382
{
×
383
    return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_APP_LAYER_PROTOCOL, SIG_MASK_REQUIRE_FLOW,
×
384
            PrefilterPacketAppProtoSet, PrefilterPacketAppProtoCompare,
×
385
            PrefilterPacketAppProtoMatch);
×
386
}
×
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
{
7✔
399
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].name = "app-layer-protocol";
7✔
400
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].desc = "match on the detected app-layer protocol";
7✔
401
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].url = "/rules/app-layer.html#app-layer-protocol";
7✔
402
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Match = DetectAppLayerProtocolPacketMatch;
7✔
403
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Setup = DetectAppLayerProtocolSetup;
7✔
404
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Free = DetectAppLayerProtocolFree;
7✔
405
#ifdef UNITTESTS
406
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].RegisterTests = DetectAppLayerProtocolRegisterTests;
407
#endif
408
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].flags =
7✔
409
            (SIGMATCH_QUOTES_OPTIONAL | SIGMATCH_HANDLE_NEGATION | SIGMATCH_SUPPORT_FIREWALL);
7✔
410

411
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SetupPrefilter = PrefilterSetupAppProto;
7✔
412
    sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SupportsPrefilter = PrefilterAppProtoIsPrefilterable;
7✔
413
}
7✔
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