1 /* $Id$ */
2 /*
3 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4 ** Copyright (C) 2004-2013 Sourcefire, Inc.
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License Version 2 as
8 ** published by the Free Software Foundation. You may not use, modify or
9 ** distribute this program under any other version of the GNU General
10 ** Public License.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21 /**
22 ** @file event_queue.c
23 **
24 ** @author Daniel Roelker <droelker@sourcefire.com>
25 ** @author Marc Norton <mnorton@sourcefire.com>
26 **
27 ** @brief Snort wrapper to sfeventq library.
28 **
29 ** These functions wrap the sfeventq API and provide the priority
30 ** functions for ordering incoming events.
31 **
32 ** Notes:
33 ** 11/1/05 Updates to add support for rules for all events in
34 ** decoders and preprocessors and the detection engine.
35 ** Added support for rule by rule flushing control via
36 ** metadata. Also added code to check fo an otn for every
37 ** event (gid,sid pair). This is now required to get events
38 ** to be logged. The decoders and preprocessors are still
39 ** configured independently, which allows them to inspect and
40 ** call the alerting functions SnortEventqAdd, GenerateSnortEvent()
41 ** and GenerateEvent2() for sfportscan.c. The GenerateSnortEvent()
42 ** function now finds and otn and calls fpLogEvent.
43 **
44 ** Any event that has no otn associated with it's gid,sid pair,
45 ** will/should not alert, even if the preprocessor or decoiderr is
46 ** configured to detect an alertable event.
47 **
48 ** In the future, preporcessor may have an api that gets called
49 ** after rules are loaded that checks for the gid/sid -> otn
50 ** mapping, and then adjusts it's inspection or detection
51 ** accordingly.
52 **
53 ** SnortEventqAdd() - only adds events that have an otn
54 **
55 */
56 #ifdef HAVE_CONFIG_H
57 #include "config.h"
58 #endif
59
60 #include "sf_types.h"
61 #include "fpcreate.h"
62 #include "fpdetect.h"
63 #include "util.h"
64 #include "sfeventq.h"
65 #include "event_wrapper.h"
66 #include "event_queue.h"
67 #include "sfthreshold.h"
68 #include "sfPolicy.h"
69 #include "sfPolicyData.h"
70
71 //-------------------------------------------------
72 // the push/pop methods ensure that qIndex stays in
73 // bounds and that it is only popped after it was
74 // successfully pushed.
75 static unsigned qIndex = 0;
76 static unsigned qOverflow = 0;
77
78 static unsigned s_events = 0;
79
80 // inline functions
81
82 /* Get the event queue at the top of the stack */
getEventQueue(void)83 static inline SF_EVENTQ *getEventQueue(void)
84 {
85 return snort_conf->event_queue[qIndex];
86 }
87
88 // API functions
SnortEventqPush(void)89 void SnortEventqPush(void)
90 {
91 if ( qIndex < NUM_EVENT_QUEUES-1 ) qIndex++;
92 else qOverflow++;
93 }
94
SnortEventqPop(void)95 void SnortEventqPop(void)
96 {
97 if ( qOverflow > 0 ) qOverflow--;
98 else if ( qIndex > 0 ) qIndex--;
99 }
100
101 //-------------------------------------------------
102 /*
103 ** Set default values
104 */
EventQueueConfigNew(void)105 EventQueueConfig * EventQueueConfigNew(void)
106 {
107 EventQueueConfig *eq =
108 (EventQueueConfig *)SnortAlloc(sizeof(EventQueueConfig));
109
110 eq->max_events = 8;
111 eq->log_events = 3;
112
113 eq->order = SNORT_EVENTQ_CONTENT_LEN;
114 eq->process_all_events = 0;
115
116 return eq;
117 }
118
EventQueueConfigFree(EventQueueConfig * eq)119 void EventQueueConfigFree(EventQueueConfig *eq)
120 {
121 if (eq == NULL)
122 return;
123
124 free(eq);
125 }
126
SnortEventqAdd(uint32_t gid,uint32_t sid,uint32_t rev,uint32_t classification,uint32_t priority,const char * msg,void * rule_info)127 int SnortEventqAdd(
128 uint32_t gid,
129 uint32_t sid,
130 uint32_t rev,
131 uint32_t classification,
132 uint32_t priority,
133 const char * msg,
134 void * rule_info
135 )
136 {
137 EventNode *en;
138 OptTreeNode *otn = (OptTreeNode *) rule_info;
139
140 if (!otn)
141 otn = GetApplicableOtn(gid, sid, rev, classification, priority, msg);
142 else if (!getRtnFromOtn(otn, getApplicableRuntimePolicy(gid)))
143 otn = NULL;
144
145 if (otn)
146 {
147 en = (EventNode *) sfeventq_event_alloc(getEventQueue());
148 if (!en)
149 return -1;
150
151 en->gid = gid;
152 en->sid = sid;
153 en->rev = rev;
154 en->classification = classification;
155 en->priority = priority;
156 en->msg = msg;
157 en->rule_info = rule_info;
158
159 if (sfeventq_add(getEventQueue(), (void *) en) != 0)
160 return -1;
161
162 s_events++;
163 }
164
165 return 0;
166 }
167
SnortEventqNew(EventQueueConfig * eq_config,SF_EVENTQ * eq[])168 void SnortEventqNew(
169 EventQueueConfig *eq_config, SF_EVENTQ *eq[]
170 ) {
171 int i;
172
173 for ( i = 0; i < NUM_EVENT_QUEUES; i++ )
174 {
175 eq[i] = sfeventq_new(eq_config->max_events,
176 eq_config->log_events, sizeof(EventNode));
177
178 if (eq[i] == NULL)
179 FatalError("Failed to initialize Snort event queue.\n");
180 }
181 }
182
SnortEventqFree(SF_EVENTQ * eq[])183 void SnortEventqFree(SF_EVENTQ *eq[])
184 {
185 int i;
186 for ( i = 0; i < NUM_EVENT_QUEUES; i++ )
187 sfeventq_free(eq[i]);
188 }
189
LogSnortEvents(void * event,void * user)190 static int LogSnortEvents(void * event, void * user)
191 {
192 EventNode *en = (EventNode *) event;
193 SNORT_EVENTQ_USER *snort_user = (SNORT_EVENTQ_USER *) user;
194 OptTreeNode *otn;
195 RuleTreeNode *rtn = NULL;
196
197 if (!event || !user)
198 return 0;
199
200 if (s_events > 0)
201 s_events--;
202
203 if (en->rule_info)
204 {
205 otn = en->rule_info;
206 }
207 else
208 {
209 // The above en->rule_info may be NULL to avoid performing an OTN/RTN
210 // lookup until after policy switching is finalized. In that case,
211 // perform the lookup here.
212 otn = GetApplicableOtn(
213 en->gid,
214 en->sid,
215 en->rev,
216 en->classification,
217 en->priority,
218 en->msg
219 );
220 }
221
222 if (otn)
223 {
224 rtn = getRtnFromOtn(otn, getApplicableRuntimePolicy(en->gid));
225 if (rtn)
226 {
227 snort_user->rule_alert = otn->sigInfo.rule_flushing;
228 LogSnortEvent((Packet *) snort_user->pkt, otn, rtn, en->msg);
229 }
230 }
231
232 sfthreshold_reset();
233
234 return 0;
235 }
236
237 /*
238 ** NAME
239 ** SnortEventqLog::
240 */
241 /**
242 ** We return whether we logged events or not. We've add a eventq user
243 ** structure so we can track whether the events logged were rule events
244 ** or preprocessor/decoder events. The reason being that we don't want
245 ** to flush a TCP stream for preprocessor/decoder events, and cause
246 ** early flushing of the stream.
247 **
248 ** @return 1 logged events
249 ** @return 0 did not log events or logged only decoder/preprocessor events
250 */
SnortEventqLog(SF_EVENTQ * eq[],Packet * p)251 int SnortEventqLog(SF_EVENTQ *eq[], Packet *p)
252 {
253 static SNORT_EVENTQ_USER user;
254
255 user.rule_alert = 0x00;
256 user.pkt = (void *)p;
257
258 if (sfeventq_action(eq[qIndex], LogSnortEvents, (void *)&user) > 0)
259 {
260 if (user.rule_alert)
261 return 1;
262 }
263
264 return 0;
265 }
266
reset_counts(void)267 static inline void reset_counts (void)
268 {
269 pc.log_limit += s_events;
270 s_events = 0;
271 }
272
SnortEventqResetCounts(void)273 void SnortEventqResetCounts (void)
274 {
275 reset_counts();
276 }
277
SnortEventqReset(void)278 void SnortEventqReset(void)
279 {
280 sfeventq_reset(getEventQueue());
281 reset_counts();
282 }
283
284