Coverage Report

Created: 2026-09-06 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/src/detect-app-layer-event.c
Line
Count
Source
1
/* Copyright (C) 2007-2023 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 "threads.h"
26
#include "decode.h"
27
28
#include "app-layer.h"
29
#include "app-layer-protos.h"
30
#include "app-layer-parser.h"
31
#include "app-layer-events.h"
32
#include "app-layer-smtp.h"
33
#include "detect.h"
34
#include "detect-parse.h"
35
#include "detect-engine.h"
36
#include "detect-engine-state.h"
37
#include "detect-engine-build.h"
38
#include "detect-app-layer-event.h"
39
40
#include "flow.h"
41
#include "flow-var.h"
42
#include "flow-util.h"
43
44
#include "decode-events.h"
45
#include "util-byte.h"
46
#include "util-debug.h"
47
#include "util-enum.h"
48
#include "util-profiling.h"
49
#include "util-unittest.h"
50
#include "util-unittest-helper.h"
51
#include "stream-tcp-util.h"
52
53
88.0k
#define MAX_ALPROTO_NAME 50
54
55
typedef struct DetectAppLayerEventData_ {
56
    AppProto alproto;
57
    uint8_t event_id;
58
} DetectAppLayerEventData;
59
60
static int DetectAppLayerEventPktMatch(DetectEngineThreadCtx *det_ctx,
61
                                       Packet *p, const Signature *s, const SigMatchCtx *ctx);
62
static int DetectAppLayerEventSetup(DetectEngineCtx *, Signature *, const char *);
63
static void DetectAppLayerEventFree(DetectEngineCtx *, void *);
64
static uint8_t DetectEngineAptEventInspect(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
65
        const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
66
        uint8_t flags, void *alstate, void *tx, uint64_t tx_id);
67
static int g_applayer_events_list_id = 0;
68
69
/**
70
 * \brief Registers the keyword handlers for the "app-layer-event" keyword.
71
 */
72
void DetectAppLayerEventRegister(void)
73
79
{
74
79
    sigmatch_table[DETECT_APP_LAYER_EVENT].name = "app-layer-event";
75
79
    sigmatch_table[DETECT_APP_LAYER_EVENT].desc =
76
79
            "match on events generated by the App Layer Parsers and the protocol detection engine";
77
79
    sigmatch_table[DETECT_APP_LAYER_EVENT].url = "/rules/app-layer.html#app-layer-event";
78
79
    sigmatch_table[DETECT_APP_LAYER_EVENT].Match = DetectAppLayerEventPktMatch;
79
79
    sigmatch_table[DETECT_APP_LAYER_EVENT].Setup = DetectAppLayerEventSetup;
80
79
    sigmatch_table[DETECT_APP_LAYER_EVENT].Free = DetectAppLayerEventFree;
81
82
79
    DetectAppLayerInspectEngineRegister("app-layer-events", ALPROTO_UNKNOWN, SIG_FLAG_TOSERVER, 0,
83
79
            DetectEngineAptEventInspect, NULL);
84
79
    DetectAppLayerInspectEngineRegister("app-layer-events", ALPROTO_UNKNOWN, SIG_FLAG_TOCLIENT, 0,
85
79
            DetectEngineAptEventInspect, NULL);
86
87
79
    g_applayer_events_list_id = DetectBufferTypeGetByName("app-layer-events");
88
79
}
89
90
static uint8_t DetectEngineAptEventInspect(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
91
        const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
92
        uint8_t flags, void *alstate, void *tx, uint64_t tx_id)
93
3
{
94
3
    int r = 0;
95
3
    const AppProto alproto = f->alproto;
96
3
    const AppLayerDecoderEvents *decoder_events =
97
3
            AppLayerParserGetEventsByTx(f->proto, alproto, tx);
98
3
    if (decoder_events == NULL) {
99
0
        goto end;
100
0
    }
101
3
    const SigMatchData *smd = engine->smd;
102
3
    while (1) {
103
3
        const DetectAppLayerEventData *aled = (const DetectAppLayerEventData *)smd->ctx;
104
3
        KEYWORD_PROFILING_START;
105
106
3
        if (AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) {
107
0
            KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
108
109
0
            if (smd->is_last)
110
0
                break;
111
0
            smd++;
112
0
            continue;
113
0
        }
114
115
3
        KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
116
3
        goto end;
117
3
    }
118
119
0
    r = 1;
120
121
3
 end:
122
3
    if (r == 1) {
123
0
        return DETECT_ENGINE_INSPECT_SIG_MATCH;
124
3
    } else {
125
3
        if (AppLayerParserGetStateProgress(f->proto, alproto, tx, flags) ==
126
3
            AppLayerParserGetStateProgressCompletionStatus(alproto, flags))
127
3
        {
128
3
            return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH;
129
3
        } else {
130
0
            return DETECT_ENGINE_INSPECT_SIG_NO_MATCH;
131
0
        }
132
3
    }
133
3
}
134
135
136
static int DetectAppLayerEventPktMatch(DetectEngineThreadCtx *det_ctx,
137
                                Packet *p, const Signature *s, const SigMatchCtx *ctx)
138
9.77k
{
139
9.77k
    const DetectAppLayerEventData *aled = (const DetectAppLayerEventData *)ctx;
140
141
9.77k
    return AppLayerDecoderEventsIsEventSet(p->app_layer_events,
142
9.77k
                                           aled->event_id);
143
9.77k
}
144
145
static DetectAppLayerEventData *DetectAppLayerEventParsePkt(const char *arg,
146
                                                            AppLayerEventType *event_type)
147
6.04k
{
148
6.04k
    uint8_t event_id = 0;
149
6.04k
    if (AppLayerGetPktEventInfo(arg, &event_id) != 0) {
150
771
        SCLogError("app-layer-event keyword "
151
771
                   "supplied with packet based event - \"%s\" that isn't "
152
771
                   "supported yet.",
153
771
                arg);
154
771
        return NULL;
155
771
    }
156
157
5.27k
    DetectAppLayerEventData *aled = SCCalloc(1, sizeof(DetectAppLayerEventData));
158
5.27k
    if (unlikely(aled == NULL))
159
0
        return NULL;
160
5.27k
    aled->event_id = (uint8_t)event_id;
161
5.27k
    *event_type = APP_LAYER_EVENT_TYPE_PACKET;
162
163
5.27k
    return aled;
164
5.27k
}
165
166
static bool OutdatedEvent(const char *raw)
167
13.7k
{
168
13.7k
    if (strcmp(raw, "tls.certificate_missing_element") == 0 ||
169
13.7k
            strcmp(raw, "tls.certificate_unknown_element") == 0 ||
170
13.7k
            strcmp(raw, "tls.certificate_invalid_string") == 0) {
171
173
        return true;
172
173
    }
173
13.6k
    return false;
174
13.7k
}
175
176
static AppProto AppLayerEventGetProtoByName(char *alproto_name)
177
86.4k
{
178
86.4k
    AppProto alproto = AppLayerGetProtoByName(alproto_name);
179
86.4k
    if (alproto == ALPROTO_HTTP) {
180
        // app-layer events http refer to http1
181
11.4k
        alproto = ALPROTO_HTTP1;
182
11.4k
    }
183
86.4k
    return alproto;
184
86.4k
}
185
186
static int DetectAppLayerEventSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
187
94.0k
{
188
94.0k
    if (arg == NULL) {
189
0
        SCLogError("app-layer-event keyword supplied "
190
0
                   "with no arguments.  This keyword needs an argument.");
191
0
        return -1;
192
0
    }
193
194
95.1k
    while (*arg != '\0' && isspace((unsigned char)*arg))
195
1.05k
        arg++;
196
197
94.0k
    AppLayerEventType event_type;
198
94.0k
    DetectAppLayerEventData *data = NULL;
199
200
94.0k
    if (strchr(arg, '.') == NULL) {
201
6.04k
        data = DetectAppLayerEventParsePkt(arg, &event_type);
202
6.04k
        if (data == NULL)
203
771
            return -1;
204
88.0k
    } else {
205
88.0k
        SCLogDebug("parsing %s", arg);
206
88.0k
        char alproto_name[MAX_ALPROTO_NAME];
207
88.0k
        bool needs_detctx = false;
208
209
88.0k
        const char *p_idx = strchr(arg, '.');
210
88.0k
        if (strlen(arg) > MAX_ALPROTO_NAME) {
211
1.55k
            SCLogError("app-layer-event keyword is too long or malformed");
212
1.55k
            return -1;
213
1.55k
        }
214
86.4k
        const char *event_name = p_idx + 1; // skip .
215
        /* + 1 for trailing \0 */
216
86.4k
        strlcpy(alproto_name, arg, p_idx - arg + 1);
217
218
86.4k
        const AppProto alproto = AppLayerEventGetProtoByName(alproto_name);
219
86.4k
        if (alproto == ALPROTO_UNKNOWN) {
220
1.76k
            if (!strcmp(alproto_name, "file")) {
221
2
                needs_detctx = true;
222
1.76k
            } else {
223
1.76k
                SCLogError("app-layer-event keyword "
224
1.76k
                           "supplied with unknown protocol \"%s\"",
225
1.76k
                        alproto_name);
226
1.76k
                return -1;
227
1.76k
            }
228
1.76k
        }
229
84.7k
        if (OutdatedEvent(arg)) {
230
2.06k
            if (SigMatchStrictEnabled(DETECT_APP_LAYER_EVENT)) {
231
0
                SCLogError("app-layer-event keyword no longer supports event \"%s\"", arg);
232
0
                return -1;
233
2.06k
            } else {
234
2.06k
                SCLogWarning("app-layer-event keyword no longer supports event \"%s\"", arg);
235
2.06k
                return -3;
236
2.06k
            }
237
2.06k
        }
238
239
82.6k
        uint8_t ipproto = 0;
240
82.6k
        if (s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8)) {
241
77.8k
            ipproto = IPPROTO_TCP;
242
77.8k
        } else if (s->proto.proto[IPPROTO_UDP / 8] & 1 << (IPPROTO_UDP % 8)) {
243
4.78k
            ipproto = IPPROTO_UDP;
244
4.78k
        } else {
245
14
            SCLogError("protocol %s is disabled", alproto_name);
246
14
            return -1;
247
14
        }
248
249
82.6k
        int r;
250
82.6k
        uint8_t event_id = 0;
251
82.6k
        if (!needs_detctx) {
252
82.6k
            r = AppLayerParserGetEventInfo(ipproto, alproto, event_name, &event_id, &event_type);
253
82.6k
        } else {
254
2
            r = DetectEngineGetEventInfo(event_name, &event_id, &event_type);
255
2
        }
256
82.6k
        if (r < 0) {
257
13.8k
            if (SigMatchStrictEnabled(DETECT_APP_LAYER_EVENT)) {
258
0
                SCLogError("app-layer-event keyword's "
259
0
                           "protocol \"%s\" doesn't have event \"%s\" registered",
260
0
                        alproto_name, event_name);
261
0
                return -1;
262
13.8k
            } else {
263
13.8k
                SCLogWarning("app-layer-event keyword's "
264
13.8k
                             "protocol \"%s\" doesn't have event \"%s\" registered",
265
13.8k
                        alproto_name, event_name);
266
13.8k
                return -3;
267
13.8k
            }
268
13.8k
        }
269
68.8k
        data = SCCalloc(1, sizeof(*data));
270
68.8k
        if (unlikely(data == NULL))
271
0
            return -1;
272
68.8k
        data->alproto = alproto;
273
68.8k
        data->event_id = (uint8_t)event_id;
274
68.8k
    }
275
74.0k
    SCLogDebug("data->event_id %u", data->event_id);
276
277
74.0k
    if (event_type == APP_LAYER_EVENT_TYPE_PACKET) {
278
5.27k
        if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_APP_LAYER_EVENT, (SigMatchCtx *)data,
279
5.27k
                    DETECT_SM_LIST_MATCH) == NULL) {
280
0
            goto error;
281
0
        }
282
68.8k
    } else {
283
68.8k
        if (SCDetectSignatureSetAppProto(s, data->alproto) != 0)
284
151
            goto error;
285
286
68.6k
        if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_APP_LAYER_EVENT, (SigMatchCtx *)data,
287
68.6k
                    g_applayer_events_list_id) == NULL) {
288
0
            goto error;
289
0
        }
290
68.6k
        s->flags |= SIG_FLAG_APPLAYER;
291
68.6k
    }
292
293
73.9k
    return 0;
294
295
151
error:
296
151
    if (data) {
297
151
        DetectAppLayerEventFree(de_ctx, data);
298
151
    }
299
151
    return -1;
300
74.0k
}
301
302
static void DetectAppLayerEventFree(DetectEngineCtx *de_ctx, void *ptr)
303
74.0k
{
304
74.0k
    SCFree(ptr);
305
74.0k
}