suricata
detect-app-layer-state.c
Go to the documentation of this file.
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 Victor Julien <vjulien@oisf.net>
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-smtp.h"
32#include "detect.h"
33#include "detect-parse.h"
34#include "detect-engine.h"
35#include "detect-engine-state.h"
36#include "detect-engine-build.h"
38
39#include "flow.h"
40#include "flow-var.h"
41#include "flow-util.h"
42
43#include "decode-events.h"
44#include "util-byte.h"
45#include "util-debug.h"
46#include "util-enum.h"
47#include "util-profiling.h"
48#include "util-unittest.h"
50#include "stream-tcp-util.h"
51
56
57static int DetectAppLayerStateSetup(DetectEngineCtx *, Signature *, const char *);
58static void DetectAppLayerStateFree(DetectEngineCtx *, void *);
59static uint8_t DetectEngineAptStateInspect(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
60 const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
61 uint8_t flags, void *alstate, void *tx, uint64_t tx_id);
62static int g_applayer_state_list_id = 0;
63
65{
66 sigmatch_table[DETECT_APP_LAYER_STATE].name = "app-layer-state";
68 "match on events generated by the App Layer Parsers and the protocol detection engine";
69 sigmatch_table[DETECT_APP_LAYER_STATE].url = "/rules/app-layer.html#app-layer-event";
70 sigmatch_table[DETECT_APP_LAYER_STATE].Setup = DetectAppLayerStateSetup;
71 sigmatch_table[DETECT_APP_LAYER_STATE].Free = DetectAppLayerStateFree;
72
74 DetectEngineAptStateInspect, NULL);
76 DetectEngineAptStateInspect, NULL);
77
78 g_applayer_state_list_id = DetectBufferTypeGetByName("app-layer-state");
79}
80
81static uint8_t DetectEngineAptStateInspect(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
82 const struct DetectEngineAppInspectionEngine_ *engine, const Signature *s, Flow *f,
83 uint8_t flags, void *alstate, void *tx, uint64_t tx_id)
84{
85 int r = 0;
86 const AppProto alproto = f->alproto;
87 const uint8_t tx_progress =
88 (uint8_t)AppLayerParserGetStateProgress(f->proto, alproto, tx, flags);
89
90 const SigMatchData *smd = engine->smd;
91 while (1) {
92 const DetectAppLayerStateData *data = (const DetectAppLayerStateData *)smd->ctx;
94
95 bool match = false;
96 if (data->mode == -1) {
97 SCLogDebug("sid:%u tx_progress %u < keyword progress %u ?", s->id, tx_progress,
98 data->progress);
99 if (tx_progress < data->progress) {
100 match = true;
101 }
102 } else if (data->mode == 1) {
103 SCLogDebug("sid:%u tx_progress %u > keyword progress %u ?", s->id, tx_progress,
104 data->progress);
105 if (tx_progress > data->progress) {
106 match = true;
107 }
108 } else {
109 BUG_ON(1);
110 }
111
112 if (match) {
113 KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
114
115 if (smd->is_last)
116 break;
117 smd++;
118 continue;
119 }
120
121 KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
122 goto end;
123 }
124 r = 1;
125
126end:
127 if (r == 1) {
128 SCLogDebug("DETECT_ENGINE_INSPECT_SIG_MATCH");
130 } else {
131 if (AppLayerParserGetStateProgress(f->proto, alproto, tx, flags) ==
133 SCLogDebug("DETECT_ENGINE_INSPECT_SIG_CANT_MATCH");
135 } else {
136 SCLogDebug("DETECT_ENGINE_INSPECT_SIG_NO_MATCH");
138 }
139 }
140}
141
142// TODO dedup with detect-parse.c
143static SignatureHook SetAppHook(const AppProto alproto, int progress)
144{
145 SignatureHook h = {
147 .t.app.alproto = alproto,
148 .t.app.app_progress = progress,
149 };
150 return h;
151}
152
153static int DetectAppLayerStateSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
154{
155 if (s->alproto == ALPROTO_UNKNOWN) {
156 return -1;
157 }
158
159 int mode = 0;
160
161 if (strlen(arg) > 0) {
162 if (arg[0] == '<') {
163 mode = -1;
164 arg++;
165 } else if (arg[0] == '>') {
166 mode = 1;
167 arg++;
168 }
169 }
170
171 if (mode == 0) {
172 const char *h = arg;
173
174 const int progress_ts = AppLayerParserGetStateIdByName(
175 IPPROTO_TCP /* TODO */, s->alproto, h, STREAM_TOSERVER);
176 if (progress_ts >= 0) {
178 s->init_data->hook = SetAppHook(s->alproto, progress_ts);
179 } else {
180 const int progress_tc = AppLayerParserGetStateIdByName(
181 IPPROTO_TCP /* TODO */, s->alproto, h, STREAM_TOCLIENT);
182 if (progress_tc < 0) {
183 return -1;
184 }
186 s->init_data->hook = SetAppHook(s->alproto, progress_tc);
187 }
188 SCLogDebug("hook %u", s->init_data->hook.t.app.app_progress);
189 return 0;
190 }
191
192 int progress = 0;
193 const char *h = arg;
194 const int progress_ts =
195 AppLayerParserGetStateIdByName(IPPROTO_TCP /* TODO */, s->alproto, h, STREAM_TOSERVER);
196 if (progress_ts >= 0) {
198 progress = progress_ts;
199 } else {
200 const int progress_tc = AppLayerParserGetStateIdByName(
201 IPPROTO_TCP /* TODO */, s->alproto, h, STREAM_TOCLIENT);
202 if (progress_tc < 0) {
203 return -1;
204 }
206 progress = progress_tc;
207 }
208
209 DetectAppLayerStateData *data = SCCalloc(1, sizeof(*data));
210 if (data == NULL)
211 return -1;
212
213 data->progress = (uint8_t)progress;
214 data->mode = (int8_t)mode;
215
217 g_applayer_state_list_id) == NULL) {
218 SCFree(data);
219 return -1;
220 }
222
223 return 0;
224}
225
226static void DetectAppLayerStateFree(DetectEngineCtx *de_ctx, void *ptr)
227{
228 SCFree(ptr);
229}
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
int AppLayerParserGetStateIdByName(uint8_t ipproto, AppProto alproto, const char *name, const uint8_t direction)
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
uint16_t AppProto
@ ALPROTO_UNKNOWN
uint8_t flags
Definition decode-gre.h:0
void DetectAppLayerStateRegister(void)
struct DetectAppLayerStateData_ DetectAppLayerStateData
@ DETECT_APP_LAYER_STATE
Data structures and function prototypes for keeping state for the detection engine.
#define DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
int DetectBufferTypeGetByName(const char *name)
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigTableElmt * sigmatch_table
#define SIG_FLAG_TOCLIENT
Definition detect.h:272
#define SIG_FLAG_TOSERVER
Definition detect.h:271
@ SIGNATURE_HOOK_TYPE_APP
Definition detect.h:549
#define SIG_FLAG_APPLAYER
Definition detect.h:249
DetectEngineCtx * de_ctx
main detection engine ctx
Definition detect.h:932
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
AppProto alproto
application level protocol
Definition flow.h:450
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
Data needed for Match()
Definition detect.h:365
bool is_last
Definition detect.h:367
SigMatchCtx * ctx
Definition detect.h:368
uint16_t type
Definition detect.h:366
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
const char * desc
Definition detect.h:1461
const char * name
Definition detect.h:1459
union SignatureHook_::@95 t
struct SignatureHook_::@95::@96 app
int app_progress
Definition detect.h:579
enum SignatureHookType type
Definition detect.h:572
SignatureHook hook
Definition detect.h:590
Signature container.
Definition detect.h:668
uint32_t flags
Definition detect.h:669
SignatureInitData * init_data
Definition detect.h:747
AppProto alproto
Definition detect.h:673
uint32_t id
Definition detect.h:713
#define BUG_ON(x)
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define KEYWORD_PROFILING_END(ctx, type, m)
#define KEYWORD_PROFILING_START