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

jasonish / suricata / 22802647571

07 Mar 2026 04:23PM UTC coverage: 75.827% (-3.4%) from 79.233%
22802647571

push

github

jasonish
github-ci: add schema ordering check for yaml schema

253365 of 334137 relevant lines covered (75.83%)

3384729.69 hits per line

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

86.54
/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
{
1,340✔
60
    SCEnter();
1,340✔
61

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

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

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

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

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

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

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

215
    return data;
65✔
216
}
65✔
217

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

417
#ifdef UNITTESTS
418

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

681

682
static void DetectAppLayerProtocolRegisterTests(void)
683
{
1✔
684
    UtRegisterTest("DetectAppLayerProtocolTest01",
1✔
685
                   DetectAppLayerProtocolTest01);
1✔
686
    UtRegisterTest("DetectAppLayerProtocolTest02",
1✔
687
                   DetectAppLayerProtocolTest02);
1✔
688
    UtRegisterTest("DetectAppLayerProtocolTest03",
1✔
689
                   DetectAppLayerProtocolTest03);
1✔
690
    UtRegisterTest("DetectAppLayerProtocolTest04",
1✔
691
                   DetectAppLayerProtocolTest04);
1✔
692
    UtRegisterTest("DetectAppLayerProtocolTest05",
1✔
693
                   DetectAppLayerProtocolTest05);
1✔
694
    UtRegisterTest("DetectAppLayerProtocolTest06",
1✔
695
                   DetectAppLayerProtocolTest06);
1✔
696
    UtRegisterTest("DetectAppLayerProtocolTest07",
1✔
697
                   DetectAppLayerProtocolTest07);
1✔
698
    UtRegisterTest("DetectAppLayerProtocolTest08",
1✔
699
                   DetectAppLayerProtocolTest08);
1✔
700
    UtRegisterTest("DetectAppLayerProtocolTest09",
1✔
701
                   DetectAppLayerProtocolTest09);
1✔
702
    UtRegisterTest("DetectAppLayerProtocolTest10",
1✔
703
                   DetectAppLayerProtocolTest10);
1✔
704
    UtRegisterTest("DetectAppLayerProtocolTest11",
1✔
705
                   DetectAppLayerProtocolTest11);
1✔
706
    UtRegisterTest("DetectAppLayerProtocolTest12",
1✔
707
                   DetectAppLayerProtocolTest12);
1✔
708
    UtRegisterTest("DetectAppLayerProtocolTest13",
1✔
709
                   DetectAppLayerProtocolTest13);
1✔
710
    UtRegisterTest("DetectAppLayerProtocolTest14",
1✔
711
                   DetectAppLayerProtocolTest14);
1✔
712
}
1✔
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