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