1 /* $Id$ */
2 /****************************************************************************
3  *
4  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
5  * Copyright (C) 2005-2013 Sourcefire, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License Version 2 as
9  * published by the Free Software Foundation.  You may not use, modify or
10  * distribute this program under any other version of the GNU General
11  * Public License.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *
22  ****************************************************************************/
23 
24 /**
25  * @file    spp_session.c
26  * @author  davis mcpherson <dmcpherson@sourcefire.com>
27  * @date    22 Feb 2013
28  *
29  * @brief  sessions? we don't got no sessions...
30  */
31 
32 /*  I N C L U D E S  ************************************************/
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #include <assert.h>
38 #include <stdio.h>
39 
40 #ifndef WIN32
41 #include <sys/time.h>       /* struct timeval */
42 #endif
43 #include <sys/types.h>      /* u_int*_t */
44 
45 #include "snort.h"
46 #include "snort_bounds.h"
47 #include "util.h"
48 #include "snort_debug.h"
49 #include "mempool.h"
50 #include "mstring.h"
51 #include "memory_stats.h"
52 #include "detect.h"
53 #include "active.h"
54 #include "sp_flowbits.h"
55 #include "packet_time.h"
56 
57 #include "session_expect.h"
58 #include "snort_session.h"
59 #include "session_api.h"
60 #include "spp_session.h"
61 #include "reload.h"
62 #include "snort_stream_tcp.h"
63 #include "snort_stream_udp.h"
64 #include "snort_stream_ip.h"
65 #include "snort_stream_icmp.h"
66 
67 #include "reg_test.h"
68 
69 #ifdef ENABLE_HA
70 #include "stream5_ha.h"
71 #endif
72 
73 #ifdef PERF_PROFILING
74 PreprocStats sessionPerfStats;
75 # ifdef ENABLE_HA
76 extern PreprocStats sessionHAPerfStats;
77 # endif
78 #endif
79 
80 extern OptTreeNode *otn_tmp;
81 
82 /*  M A C R O S  **************************************************/
83 
84 /*  G L O B A L S  **************************************************/
85 SessionStatistics session_stats;
86 uint32_t firstPacketTime = 0;
87 uint32_t session_mem_in_use = 0;
88 
89 SessionConfiguration *session_configuration = NULL;
90 static SessionConfiguration *session_reload_configuration = NULL;
91 static GetHttpXffPrecedenceFunc getHttpXffPrecedenceFunc = NULL;
92 
93 SessionCache *proto_session_caches[ SESSION_PROTO_MAX ];
94 
95 MemPool sessionFlowMempool;
96 
97 static PreprocEnableMask appHandlerDispatchMask[ INT16_MAX ];
98 
99 static sfaddr_t fixed_addr = {{{{0xFF,0,0,0}}},0}; /* Used in lieu of ICMPv6/ICMP multicast/broadcast address
100 * to generate a matching key in between router solicitation and advertisement to associate them in one session.
101 * In future, we can extend this approach to other types of services (may need support in snort's decode):
102 *  - Multicast Listener Query (MLD) types 130-131-132 (typically multicast dest),
103 *  - ICMP Node Information Query types 139-140 (unicast or multicast dest),
104 *  - Neighbor Solicitation Message Format types 135-136 (unicast or multicast dest),
105 *  - Echo Request/Reply types 128-129 ping6 and 8-0 ping (unicast/multicast/broadcast dest), etc.
106 */
107 
108 /*  P R O T O T Y P E S  ********************************************/
109 void initializeSessionPreproc(struct _SnortConfig *, char *);
110 static void parseSessionConfiguration(SessionConfiguration *, char *);
111 static void exitSessionCleanly(int, void *);
112 static void resetSessionState(int, void *);
113 static void resetSessionStatistics(int, void *);
114 static int  verifySessionConfig(struct _SnortConfig *);
115 static void printSessionConfiguration(SessionConfiguration *);
116 static void printSessionStatistics(int);
117 static void sessionPacketProcessor(Packet *p, void *context);
118 
119 #ifdef SNORT_RELOAD
120 static void reloadSessionConfiguration( struct _SnortConfig *, char *, void ** );
121 static int verifyReloadedSessionConfiguration( struct _SnortConfig *, void * );
122 static void *activateSessionConfiguration( struct _SnortConfig *sc, void *data );
123 static void freeSessionConfiguration( void * );
124 #endif
125 
126 /*  S E S S I O N A P I **********************************************/
127 #if 0
128 static void PrintSessionKey(SessionKey *);
129 #endif
130 
131 #ifdef MPLS
132 static void initMplsHeaders(SessionControlBlock*);
133 static void freeMplsHeaders(SessionControlBlock*);
134 #endif
135 
136 static SessionCache* initSessionCache(uint32_t session_type, uint32_t protocol_scb_size, SessionCleanup clean_fcn);
137 static void *getSessionControlBlock(SessionCache*, Packet *, SessionKey *);
138 static void *checkSessionControlBlock(void *, Packet *, SessionKey *);
139 static void updateSessionControlBlockTime(SessionControlBlock *, Packet *);
140 static void populateSessionKey(Packet *p, SessionKey *key);
141 static int initSessionKeyFromPktHeader( sfaddr_t* srcIP, uint16_t srcPort, sfaddr_t* dstIP,
142                                         uint16_t dstPort, char proto, uint16_t vlan,
143                                         uint32_t mplsId,
144 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
145                                         uint16_t address_space_id_src,
146                                         uint16_t address_space_id_dst,
147 #else
148                                         uint16_t addressSpaceId,
149 #endif
150 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
151                                         uint32_t carrierId,
152 #endif
153                                         SessionKey *key);
154 static void *getSessionControlBlockFromKey(SessionCache*, const SessionKey *);
155 static void *getSessionHandle(const SessionKey *key);
156 static void *createSession(SessionCache*, Packet *, const SessionKey * );
157 static bool isSessionVerified( void * );
158 static void removeSessionFromProtoOneWayList(uint32_t proto, void *scb);
159 static int deleteSession(SessionCache*, void *, char *reason, bool close_sync);
160 static int deleteSessionByKey(void *, char *reason);
161 static void printSessionCache(SessionCache*);
162 static int deleteSessionCache(uint32_t protocol);
163 static int purgeSessionCache(SessionCache*);
164 static int pruneSessionCache(SessionCache*, uint32_t thetime, void *save_me, int memcheck);
165 static void cleanProtocolSessionsPool( uint32_t  );
166 static void freeProtocolSessionsPool( uint32_t, void * );
167 static void *allocateProtocolSession( uint32_t );
168 static int getActiveSessionCount(SessionCache*);
169 static uint32_t getSessionPruneCount( uint32_t );
170 static void resetSessionPruneCount( uint32_t );
171 static void checkSessionTimeout( uint32_t, time_t );
172 static void setPacketDirectionFlag(Packet *p, void *scb);
173 static void freeSessionApplicationData(void *scb);
174 
175 static int isProtocolTrackingEnabled( IpProto proto );
176 static uint32_t getPacketDirection( Packet *p );
177 static void disableInspection(void *scbptr, Packet *p);
178 static void stopInspection( void * scbptr, Packet *p, char dir, int32_t bytes, int response );
179 struct _ExpectNode;
180 static int ignoreChannel( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort, sfaddr_t* dstIP,
181         uint16_t dstPort, uint8_t protocol, uint32_t preprocId, char direction, char flags,
182         struct _ExpectNode** packetExpectedNode);
183 static int getIgnoreDirection( void *scbptr );
184 static int setIgnoreDirection( void *scbptr, int );
185 static void resumeInspection( void *scbptr, char dir );
186 static void dropTraffic( Packet*, void *scbptr, char dir );
187 static int setApplicationData( void *scbptr, uint32_t protocol, void *data, StreamAppDataFree free_func );
188 static void *getApplicationData( void *scbptr, uint32_t protocol );
189 static StreamSessionKey * getSessionKeyFromPacket( Packet *p );
190 static void * getApplicationDataFromSessionKey( const StreamSessionKey *key, uint32_t protocol);
191 static void *getApplicationDataFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
192                                            sfaddr_t* dstIP, uint16_t dstPort,
193 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
194                                            uint16_t address_space_id_src,
195                                            uint16_t address_space_id_dst,
196 #else
197                                            uint16_t addressSpaceId,
198 #endif
199 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
200                                            uint32_t carrierId,
201 #endif
202                                            char ip_protocol, uint16_t vlan,
203                                            uint32_t mplsId, uint32_t protocol );
204 static void setSessionExpirationTime(Packet *p, void *scbptr, uint32_t timeout);
205 static int getSessionExpirationTime(Packet *p, void *scbptr);
206 static uint32_t setSessionFlags( void *scbptr, uint32_t flags );
207 static uint32_t getSessionFlags( void *scbptr );
208 static tSfPolicyId getSessionPolicy(void *scbptr, int policy_type);
209 static void setSessionPolicy(void *scbptr, int policy_type, tSfPolicyId id);
210 static StreamFlowData *getFlowData( Packet *p );
211 static void setSessionDeletionDelayed( void *scbptr, bool delay_session_deletion_flag);
212 static bool isSessionDeletionDelayed( void *scbptr );
213 static int setAppProtocolIdExpected( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort, sfaddr_t* dstIP,
214         uint16_t dstPort, uint8_t protocol, int16_t protoId, uint32_t preprocId,
215         void* protoData, void (*protoDataFreeFn)(void*),
216         struct _ExpectNode** packetExpectedNode);
217 #ifdef TARGET_BASED
218 static void registerApplicationHandler( uint32_t preproc_id, int16_t app_id );
219 static int16_t getAppProtocolId( void *scbptr );
220 static int16_t setAppProtocolId( void *scbptr, int16_t id );
221 static sfaddr_t* getSessionIpAddress( void *scbptr, uint32_t direction );
222 static void getSessionPorts( void *scbptr, uint16_t *client_port, uint16_t *server_port );
223 #endif
224 
225 static uint16_t getPreprocessorStatusBit( void );
226 static void getMaxSessions(tSfPolicyId policyId, StreamSessionLimits* limits);
227 static void *getSessionHandleFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
228                                          sfaddr_t* dstIP, uint16_t dstPort,
229                                          char ip_protocol, uint16_t vlan,
230                                          uint32_t mplsId,
231 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
232                                          uint16_t address_space_id_src,
233                                          uint16_t address_space_id_dst
234 #else
235                                          uint16_t addressSpaceId
236 #endif
237 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
238                                          , uint32_t carrierId
239 #endif
240                                         );
241 static const StreamSessionKey *getKeyFromSession(const void *scbptr);
242 
243 #ifdef TARGET_BASED
244 #ifdef ACTIVE_RESPONSE
245 static void initActiveResponse( Packet*, void* scbptr );
246 #endif
247 
248 static uint8_t getHopLimit ( void* scbptr, char dir, int outer );
249 #endif
250 static void deleteSessionIfClosed( Packet* );
251 static void disablePreprocForSession( void *scbptr, uint32_t preproc_id );
252 static void enablePreprocForPort( SnortConfig *sc, uint32_t preproc_id, uint32_t proto, uint16_t port );
253 static void enablePreprocAllPorts( SnortConfig *sc, uint32_t preproc_id, uint32_t proto );
254 static void enablePreprocAllPortsAllPolicies( SnortConfig *sc, uint32_t preproc_id, uint32_t proto );
255 static bool isPreprocEnabledForPort( uint32_t preproc_id, uint16_t port );
256 static void registerNapSelector( nap_selector nap_selector_func );
257 static void registerGetHttpXffPrecedence(GetHttpXffPrecedenceFunc fn);
258 static char** getHttpXffPrecedence(void* ssn, uint32_t flags, int* nFields);
259 static void setReputationUpdateCount (void *ssn, uint8_t count);
260 
261 SessionAPI session_api_dispatch_table = {
262     /* .version = */ SESSION_API_VERSION1,
263     /* .init_session_cache =  */  initSessionCache,
264     /* .get_session = */ getSessionControlBlock,
265     /* .populate_session_key = */ populateSessionKey,
266     /* .get_session_key_by_ip_port = */ initSessionKeyFromPktHeader,
267     /* .get_session_by_key = */ getSessionControlBlockFromKey,
268     /* .get_session_handle = */ getSessionHandle,
269     /* .create_session = */ createSession,
270     /* .is_session_verified = */ isSessionVerified,
271     /* .remove_session_from_oneway_list = */ removeSessionFromProtoOneWayList,
272     /* .delete_session = */ deleteSession,
273     /* .delete_session_by_key = */ deleteSessionByKey,
274     /* .print_session_cache = */ printSessionCache,
275     /* .delete_session_cache = */ deleteSessionCache,
276     /* .purge_session_cache = */ purgeSessionCache,
277     /* .prune_session_cache = */ pruneSessionCache,
278     /* .clean_protocol_session_pool = */ cleanProtocolSessionsPool,
279     /* .free_protocol_session_pool = */ freeProtocolSessionsPool,
280     /* .alloc_protocol_session = */ allocateProtocolSession,
281     /* .get_session_count = */ getActiveSessionCount,
282     /* .get_session_prune_count = */ getSessionPruneCount,
283     /* .reset_session_prune_count = */ resetSessionPruneCount,
284     /* .check_session_timeout = */ checkSessionTimeout,
285     /* .protocol_tracking_enabled = */ isProtocolTrackingEnabled,
286     /* .set_packet_direction_flag = */ setPacketDirectionFlag,
287     /* .free_application_data = */ freeSessionApplicationData,
288     /* .get_packet_direction = */ getPacketDirection,
289     /* .disable_inspection = */ disableInspection,
290     /* .stop_inspection = */ stopInspection,
291     /* .ignore_session = */ ignoreChannel,
292     /* .get_ignore_direction = */ getIgnoreDirection,
293     /* .resume_inspection = */ resumeInspection,
294     /* .drop_traffic = */ dropTraffic,
295     /* .set_application_data = */ setApplicationData,
296     /* .get_application_data = */ getApplicationData,
297     /* .set_expire_timer = */ setSessionExpirationTime,
298     /* .get_expire_timer = */ getSessionExpirationTime,
299     /* .set_session_flags = */ setSessionFlags,
300     /* .get_session_flags = */ getSessionFlags,
301     /* .get_runtime_policy = */ getSessionPolicy,
302     /* .set_runtime_policy = */ setSessionPolicy,
303     /* .get_flow_data = */ getFlowData,
304     /* .set_session_deletion_delayed = */ setSessionDeletionDelayed,
305     /* .is_session_deletion_delayed = */ isSessionDeletionDelayed,
306 #ifdef TARGET_BASED
307     /* .register_service_handler  */ registerApplicationHandler,
308     /* .get_application_protocol_id = */ getAppProtocolId,
309     /* .set_application_protocol_id = */ setAppProtocolId,
310     /* .get_session_ip_address = */ getSessionIpAddress,
311     /* .get_session_ports = */ getSessionPorts,
312 #endif
313     /* .get_preprocessor_status_bit = */ getPreprocessorStatusBit,
314 #ifdef TARGET_BASED
315 #ifdef ACTIVE_RESPONSE
316     /* .init_active_response = */ initActiveResponse,
317 #endif
318     /* .get_session_ttl = */ getHopLimit,
319 #endif
320     /* .set_application_protocol_id_expected = */ setAppProtocolIdExpected,
321 #ifdef ENABLE_HA
322     /* .register_ha_funcs = */ RegisterSessionHAFuncs,
323     /* .unregister_ha_funcs = */ UnregisterSessionHAFuncs,
324     /* .set_ha_pending_bit = */ SessionSetHAPendingBit,
325     /* .process_ha = */ SessionProcessHA,
326 #endif
327     /* .get_max_session_limits = */ getMaxSessions,
328     /* .set_ignore_direction = */ setIgnoreDirection,
329     /* .get_session_ptr_from_ip_port = */ getSessionHandleFromIpPort,
330     /* .get_key_from_session_ptr = */ getKeyFromSession,
331     /* .check_session_closed = */ deleteSessionIfClosed,
332     /* .get_session_key = */ getSessionKeyFromPacket,
333     /* .get_application_data_from_key = */ getApplicationDataFromSessionKey,
334     /* .get_application_data_from_ip_port = */ getApplicationDataFromIpPort,
335     /* .disable_preproc_for_session = */ disablePreprocForSession,
336     /* .enable_preproc_for_port = */ enablePreprocForPort,
337     /* .enable_preproc_all_ports = */ enablePreprocAllPorts,
338     /* .enable_preproc_all_ports_all_policies = */ enablePreprocAllPortsAllPolicies,
339     /* .is_preproc_enabled_for_port = */  isPreprocEnabledForPort,
340     /* .register_nap_selector =  */   registerNapSelector,
341     /* .register_mandatory_early_session_creator = */ registerMandatoryEarlySessionCreator,
342     /* .get_application_data_from_expected_node = */ getApplicationDataFromExpectedNode,
343     /* .add_application_data_to_expected_node = */ addApplicationDataToExpectedNode,
344     /* .register_get_http_xff_precedence = */ registerGetHttpXffPrecedence,
345     /* .get_http_xff_precedence = */ getHttpXffPrecedence,
346     /* .get_next_expected_node = */ getNextExpectedNode,
347     /* .set_reputation_update_counter = */ setReputationUpdateCount
348 };
349 
350 
SetupSessionManager(void)351 void SetupSessionManager(void)
352 {
353 #ifndef SNORT_RELOAD
354     RegisterPreprocessor("stream5_global", initializeSessionPreproc);
355 # ifdef ENABLE_HA
356     RegisterPreprocessor("stream5_ha", StreamHAInit);
357 # endif
358 #else
359     RegisterPreprocessor("stream5_global",
360             initializeSessionPreproc,
361             reloadSessionConfiguration,
362             verifyReloadedSessionConfiguration,
363             activateSessionConfiguration,
364             freeSessionConfiguration);
365 
366 # ifdef ENABLE_HA
367     RegisterPreprocessor("stream5_ha",
368             SessionHAInit,
369             SessionHAReload,
370             SessionVerifyHAConfig,
371             SessionHASwapReload,
372             SessionHAConfigFree);
373 #endif
374 #endif
375 
376     // init the pointer to session api dispatch table
377     session_api = &session_api_dispatch_table;
378 
379     DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Preprocessor Session is setup\n"););
380 }
381 
selectRuntimePolicy(Packet * p,bool client_packet)382 static void selectRuntimePolicy( Packet *p, bool client_packet )
383 {
384     tSfPolicyId id;
385     int vlanId = ( p->vh ) ? VTH_VLAN( p->vh ) : -1;
386 
387     sfaddr_t* srcIp = ( p->iph ) ? GET_SRC_IP( p ) : NULL;
388     sfaddr_t* dstIp = ( p->iph ) ? GET_DST_IP( p ) : NULL;
389 
390     //set policy id for this packet
391     id = sfGetApplicablePolicyId( snort_conf->policy_config, vlanId, srcIp, dstIp );
392     setNapRuntimePolicy( id );
393     setIpsRuntimePolicy( id );
394     p->configPolicyId = snort_conf->targeted_policies[ id ]->configPolicyId;
395     p->ips_os_selected = true;
396 }
397 
getSessionConfiguration(bool reload_config)398 SessionConfiguration *getSessionConfiguration( bool reload_config )
399 {
400     if( reload_config )
401         return session_reload_configuration;
402     else
403         return session_configuration;
404 }
405 
initSessionConfiguration(void)406 static SessionConfiguration *initSessionConfiguration( void )
407 {
408     SessionConfiguration *sessionConfig =
409         (SessionConfiguration *)SnortPreprocAlloc(1, sizeof(SessionConfiguration),
410                                       PP_STREAM, PP_MEM_CATEGORY_CONFIG );
411 
412     sessionConfig->track_tcp_sessions = STREAM_TRACK_YES;
413     sessionConfig->max_tcp_sessions = STREAM_DEFAULT_MAX_TCP_SESSIONS;
414     sessionConfig->tcp_cache_pruning_timeout = STREAM_DEFAULT_TCP_CACHE_PRUNING_TIMEOUT;
415     sessionConfig->tcp_cache_nominal_timeout = STREAM_DEFAULT_TCP_CACHE_NOMINAL_TIMEOUT;
416     sessionConfig->track_udp_sessions = STREAM_TRACK_YES;
417     sessionConfig->max_udp_sessions = STREAM_DEFAULT_MAX_UDP_SESSIONS;
418     sessionConfig->udp_cache_pruning_timeout = STREAM_DEFAULT_UDP_CACHE_PRUNING_TIMEOUT;
419     sessionConfig->udp_cache_nominal_timeout = STREAM_DEFAULT_UDP_CACHE_NOMINAL_TIMEOUT;
420     sessionConfig->track_icmp_sessions = STREAM_TRACK_NO;
421     sessionConfig->max_icmp_sessions = STREAM_DEFAULT_MAX_ICMP_SESSIONS;
422     sessionConfig->track_ip_sessions = STREAM_TRACK_NO;
423     sessionConfig->max_ip_sessions = STREAM_DEFAULT_MAX_IP_SESSIONS;
424     sessionConfig->memcap = STREAM_DEFAULT_MEMCAP;
425     sessionConfig->prune_log_max = STREAM_DEFAULT_PRUNE_LOG_MAX;
426 #ifdef ACTIVE_RESPONSE
427     sessionConfig->max_active_responses = STREAM_DEFAULT_MAX_ACTIVE_RESPONSES;
428     sessionConfig->min_response_seconds = STREAM_DEFAULT_MIN_RESPONSE_SECONDS;
429 #endif
430 
431 #ifdef ENABLE_HA
432     sessionConfig->enable_ha = 0;
433 #endif
434 
435     return sessionConfig;
436 }
437 
initializeMaxExpectedFlows(SessionConfiguration * sessionConfig)438 void initializeMaxExpectedFlows( SessionConfiguration *sessionConfig )
439 {
440     // initialize max expected flows...
441     uint32_t max = sessionConfig->max_tcp_sessions + sessionConfig->max_udp_sessions;
442 
443     if( ( max >>= 9 ) == 0 )
444         max = 2;
445 
446     StreamExpectInit(max);
447     LogMessage("      Max Expected Streams: %u\n", max);
448 }
449 
initializeSessionPreproc(struct _SnortConfig * sc,char * args)450 void initializeSessionPreproc(struct _SnortConfig *sc, char *args)
451 {
452     if (session_configuration == NULL)
453     {
454         session_configuration = initSessionConfiguration( );
455 
456 #ifdef PERF_PROFILING
457         RegisterPreprocessorProfile("session_manager", &sessionPerfStats, 0, &totalPerfStats, NULL);
458 # ifdef ENABLE_HA
459         RegisterPreprocessorProfile("session_ha", &sessionHAPerfStats, 1, &sessionPerfStats, NULL);
460 # endif
461 #endif
462 
463         // register these to run last so other preprocs have chance to release all session
464         // related resources before session exits
465         AddFuncToPreprocCleanExitList(exitSessionCleanly, NULL, PRIORITY_LAST, PP_SESSION);
466         AddFuncToPreprocResetList(resetSessionState, NULL, PRIORITY_LAST, PP_SESSION);
467         AddFuncToPreprocResetStatsList(resetSessionStatistics, NULL, PP_SESSION_PRIORITY, PP_SESSION);
468         AddFuncToConfigCheckList(sc, verifySessionConfig);
469         RegisterPreprocStats("session_manager", printSessionStatistics);
470 
471         session_api = &session_api_dispatch_table;
472 
473 #ifdef ENABLE_HA
474         AddFuncToPostConfigList(sc, SessionHAPostConfigInit, NULL);
475 #endif
476 
477         parseSessionConfiguration(session_configuration, args);
478         if( ( !session_configuration->disabled) &&
479                 (  session_configuration->track_tcp_sessions == STREAM_TRACK_NO) &&
480                 (  session_configuration->track_udp_sessions == STREAM_TRACK_NO) &&
481                 (  session_configuration->track_icmp_sessions == STREAM_TRACK_NO) &&
482                 (  session_configuration->track_ip_sessions == STREAM_TRACK_NO))
483         {
484             FatalError("%s(%d) ==> Session enabled, but not configured to track "
485                     "TCP, UDP, ICMP, or IP.\n", file_name, file_line);
486         }
487 
488         enablePreprocAllPorts( sc, PP_SESSION, PROTO_BIT__ALL );
489         // TBD-EDM - fix reg tests when this is enabled
490         // printSessionConfiguration(session_configuration);
491 
492         // register default NAP selector, nap rule engine will overide when it is configured
493         registerNapSelector( &selectRuntimePolicy );
494         memset( appHandlerDispatchMask, 0, sizeof( appHandlerDispatchMask ) );
495         AddFuncToPreprocList(sc, sessionPacketProcessor, PP_SESSION_PRIORITY, PP_SESSION, PROTO_BIT__ALL);
496 
497         initializeMaxExpectedFlows( session_configuration );
498         sc->run_flags |= RUN_FLAG__STATEFUL;
499     }
500     else
501     {
502 #if 0
503         // EDM-TBD
504         FatalError("stream5_global must only be configured once.\n");
505 #else
506         WarningMessage("stream5_global must only be configured once. Ignoring this configuration element\n");
507 #endif
508     }
509 }
510 
parseSessionConfiguration(SessionConfiguration * config,char * args)511 static void parseSessionConfiguration( SessionConfiguration *config, char *args )
512 {
513     char **toks;
514     int num_toks;
515     int i;
516     char **stoks;
517     int s_toks;
518     char *endPtr = NULL;
519 
520     if (config == NULL)
521         return;
522 
523     if ((args == NULL) || (strlen(args) == 0))
524         return;
525 
526     toks = mSplit(args, ",", 0, &num_toks, 0);
527     i = 0;
528 
529     for (i = 0; i < num_toks; i++)
530     {
531         stoks = mSplit(toks[i], " ", 4, &s_toks, 0);
532 
533         if (s_toks == 0)
534         {
535             FatalError("%s(%d) => Missing parameter in Session config.\n",
536                     file_name, file_line);
537         }
538         if (s_toks > 2) //Trailing parameters
539         {
540             FatalError("%s(%d) => Too many parameters for option in Session config.\n",
541                     file_name, file_line);
542         }
543 
544         if(!strcasecmp(stoks[0], "memcap"))
545         {
546             if (stoks[1])
547             {
548                 config->memcap = strtoul(stoks[1], &endPtr, 10);
549             }
550 
551             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
552             {
553                 FatalError("%s(%d) => Invalid memcap in config file.  Requires integer parameter.\n",
554                         file_name, file_line);
555             }
556 
557             if ((config->memcap > STREAM_RIDICULOUS_HI_MEMCAP) ||
558                     (config->memcap < STREAM_RIDICULOUS_LOW_MEMCAP))
559             {
560                 FatalError("%s(%d) => 'memcap %s' invalid: value must be "
561                         "between %d and %d bytes\n",
562                         file_name, file_line,
563                         stoks[1], STREAM_RIDICULOUS_LOW_MEMCAP,
564                         STREAM_RIDICULOUS_HI_MEMCAP);
565             }
566         }
567         else if(!strcasecmp(stoks[0], "max_tcp"))
568         {
569             if (stoks[1])
570             {
571                 config->max_tcp_sessions = strtoul(stoks[1], &endPtr, 10);
572                 if (config->track_tcp_sessions == STREAM_TRACK_YES)
573                 {
574                     if ((config->max_tcp_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
575                             (config->max_tcp_sessions == 0))
576                     {
577                         FatalError("%s(%d) => 'max_tcp %d' invalid: value must be "
578                                 "between 1 and %d sessions\n",
579                                 file_name, file_line,
580                                 config->max_tcp_sessions,
581                                 STREAM_RIDICULOUS_MAX_SESSIONS);
582                     }
583                 }
584             }
585 
586             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
587             {
588                 FatalError("%s(%d) => Invalid max_tcp in config file.  Requires integer parameter.\n",
589                         file_name, file_line);
590             }
591         }
592         else if(!strcasecmp(stoks[0], "tcp_cache_pruning_timeout"))
593         {
594             if (stoks[1])
595             {
596                 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
597 
598                 if (config->track_tcp_sessions == STREAM_TRACK_YES)
599                 {
600                     if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
601                     {
602                         FatalError(
603                                 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
604                                 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
605                     }
606                 }
607                 config->tcp_cache_pruning_timeout = (uint16_t)timeout;
608             }
609 
610             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
611             {
612                 FatalError("%s(%d) => Invalid %s in config file.  Requires integer parameter.\n",
613                         file_name, file_line, stoks[0]);
614             }
615         }
616         else if(!strcasecmp(stoks[0], "tcp_cache_nominal_timeout"))
617         {
618             if (stoks[1])
619             {
620                 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
621 
622                 if (config->track_tcp_sessions == STREAM_TRACK_YES)
623                 {
624                     if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
625                     {
626                         FatalError(
627                                 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
628                                 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
629                     }
630                 }
631                 config->tcp_cache_nominal_timeout = (uint16_t)timeout;
632             }
633 
634             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
635             {
636                 FatalError("%s(%d) => Invalid %s in config file.  Requires integer parameter.\n",
637                         file_name, file_line, stoks[0]);
638             }
639         }
640         else if(!strcasecmp(stoks[0], "track_tcp"))
641         {
642             if (stoks[1])
643             {
644                 if(!strcasecmp(stoks[1], "no"))
645                     config->track_tcp_sessions = STREAM_TRACK_NO;
646                 else if(!strcasecmp(stoks[1], "yes"))
647                     config->track_tcp_sessions = STREAM_TRACK_YES;
648                 else
649                     FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
650                         file_name, file_line);
651             }
652             else
653             {
654                 FatalError("%s(%d) => 'track_tcp' missing option\n",
655                         file_name, file_line);
656             }
657         }
658         else if(!strcasecmp(stoks[0], "max_udp"))
659         {
660             if (stoks[1])
661             {
662                 config->max_udp_sessions = strtoul(stoks[1], &endPtr, 10);
663                 if (config->track_udp_sessions == STREAM_TRACK_YES)
664                 {
665                     if ((config->max_udp_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
666                             (config->max_udp_sessions == 0))
667                     {
668                         FatalError("%s(%d) => 'max_udp %d' invalid: value must be "
669                                 "between 1 and %d sessions\n",
670                                 file_name, file_line,
671                                 config->max_udp_sessions,
672                                 STREAM_RIDICULOUS_MAX_SESSIONS);
673                     }
674                 }
675             }
676 
677             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
678             {
679                 FatalError("%s(%d) => Invalid max_udp in config file.  Requires integer parameter.\n",
680                         file_name, file_line);
681             }
682         }
683         else if(!strcasecmp(stoks[0], "udp_cache_pruning_timeout"))
684         {
685             if (stoks[1])
686             {
687                 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
688 
689                 if (config->track_udp_sessions == STREAM_TRACK_YES)
690                 {
691                     if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
692                     {
693                         FatalError(
694                                 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
695                                 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
696                     }
697                 }
698                 config->udp_cache_pruning_timeout = (uint16_t)timeout;
699             }
700 
701             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
702             {
703                 FatalError("%s(%d) => Invalid %s in config file.  Requires integer parameter.\n",
704                         file_name, file_line, stoks[0]);
705             }
706         }
707         else if(!strcasecmp(stoks[0], "udp_cache_nominal_timeout"))
708         {
709             if (stoks[1])
710             {
711                 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
712 
713                 if (config->track_udp_sessions == STREAM_TRACK_YES)
714                 {
715                     if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
716                     {
717                         FatalError(
718                                 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
719                                 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
720                     }
721                 }
722                 config->udp_cache_nominal_timeout = (uint16_t)timeout;
723             }
724 
725             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
726             {
727                 FatalError("%s(%d) => Invalid %s in config file.  Requires integer parameter.\n",
728                         file_name, file_line, stoks[0]);
729             }
730         }
731         else if(!strcasecmp(stoks[0], "track_udp"))
732         {
733             if (stoks[1])
734             {
735                 if(!strcasecmp(stoks[1], "no"))
736                     config->track_udp_sessions = STREAM_TRACK_NO;
737                 else if(!strcasecmp(stoks[1], "yes"))
738                     config->track_udp_sessions = STREAM_TRACK_YES;
739                 else
740                     FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
741                         file_name, file_line);
742             }
743             else
744             {
745                 FatalError("%s(%d) => 'track_udp' missing option\n",
746                         file_name, file_line);
747             }
748         }
749         else if(!strcasecmp(stoks[0], "max_icmp"))
750         {
751             if (stoks[1])
752             {
753                 config->max_icmp_sessions = strtoul(stoks[1], &endPtr, 10);
754 
755                 if (config->track_icmp_sessions == STREAM_TRACK_YES)
756                 {
757                     if ((config->max_icmp_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
758                             (config->max_icmp_sessions == 0))
759                     {
760                         FatalError("%s(%d) => 'max_icmp %d' invalid: value must be "
761                                 "between 1 and %d sessions\n",
762                                 file_name, file_line,
763                                 config->max_icmp_sessions,
764                                 STREAM_RIDICULOUS_MAX_SESSIONS);
765                     }
766                 }
767             }
768 
769             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
770             {
771                 FatalError("%s(%d) => Invalid max_icmp in config file.  Requires integer parameter.\n",
772                         file_name, file_line);
773             }
774         }
775         else if(!strcasecmp(stoks[0], "track_icmp"))
776         {
777             if (stoks[1])
778             {
779                 if(!strcasecmp(stoks[1], "no"))
780                     config->track_icmp_sessions = STREAM_TRACK_NO;
781                 else if(!strcasecmp(stoks[1], "yes"))
782                     config->track_icmp_sessions = STREAM_TRACK_YES;
783                 else
784                     FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
785                         file_name, file_line);
786             }
787             else
788             {
789                 FatalError("%s(%d) => 'track_icmp' missing option\n",
790                         file_name, file_line);
791             }
792         }
793         else if(!strcasecmp(stoks[0], "max_ip"))
794         {
795             if (stoks[1])
796             {
797                 config->max_ip_sessions = strtoul(stoks[1], &endPtr, 10);
798 
799                 if (config->track_ip_sessions == STREAM_TRACK_YES)
800                 {
801                     if ((config->max_ip_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
802                             (config->max_ip_sessions == 0))
803                     {
804                         FatalError("%s(%d) => 'max_ip %d' invalid: value must be "
805                                 "between 1 and %d sessions\n",
806                                 file_name, file_line,
807                                 config->max_ip_sessions,
808                                 STREAM_RIDICULOUS_MAX_SESSIONS);
809                     }
810                 }
811             }
812 
813             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
814             {
815                 FatalError("%s(%d) => Invalid max_ip in config file.  Requires integer parameter.\n",
816                         file_name, file_line);
817             }
818         }
819         else if(!strcasecmp(stoks[0], "track_ip"))
820         {
821             if (stoks[1])
822             {
823                 if(!strcasecmp(stoks[1], "no"))
824                     config->track_ip_sessions = STREAM_TRACK_NO;
825                 else if(!strcasecmp(stoks[1], "yes"))
826                     config->track_ip_sessions = STREAM_TRACK_YES;
827                 else
828                     FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
829                         file_name, file_line);
830             }
831             else
832             {
833                 FatalError("%s(%d) => 'track_ip' missing option\n",
834                         file_name, file_line);
835             }
836         }
837         else if(!strcasecmp(stoks[0], "flush_on_alert"))
838         {
839             if (s_toks > 1) //Trailing parameters
840             {
841                 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
842                         file_name, file_line);
843             }
844             config->flags |= STREAM_CONFIG_FLUSH_ON_ALERT;
845         }
846         else if(!strcasecmp(stoks[0], "show_rebuilt_packets"))
847         {
848             if (s_toks > 1) //Trailing parameters
849             {
850                 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
851                         file_name, file_line);
852             }
853             config->flags |= STREAM_CONFIG_SHOW_PACKETS;
854         }
855         else if(!strcasecmp(stoks[0], "prune_log_max"))
856         {
857             if (stoks[1])
858             {
859                 config->prune_log_max = strtoul(stoks[1], &endPtr, 10);
860             }
861 
862             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
863             {
864                 FatalError("%s(%d) => Invalid prune_log_max in config file.  Requires integer parameter.\n",
865                         file_name, file_line);
866             }
867 
868             if (((config->prune_log_max > STREAM_MAX_PRUNE_LOG_MAX) ||
869                         (config->prune_log_max < STREAM_MIN_PRUNE_LOG_MAX)) &&
870                     (config->prune_log_max != 0))
871             {
872                 FatalError("%s(%d) => Invalid Prune Log Max."
873                         "  Must be 0 (disabled) or between %d and %d\n",
874                         file_name, file_line,
875                         STREAM_MIN_PRUNE_LOG_MAX, STREAM_MAX_PRUNE_LOG_MAX);
876             }
877         }
878 #ifdef TBD
879         else if(!strcasecmp(stoks[0], "no_midstream_drop_alerts"))
880         {
881             /*
882              * FIXTHIS: Do we want to not alert on drops for sessions picked
883              * up midstream ?  If we're inline, and get a session midstream,
884              * its because it was picked up during startup.  In inline
885              * mode, we should ALWAYS be requiring TCP 3WHS.
886              */
887             if (s_toks > 1) //Trailing parameters
888             {
889                 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
890                         file_name, file_line);
891             }
892             config->flags |= STREAM_CONFIG_MIDSTREAM_DROP_NOALERT;
893         }
894 #endif
895 #ifdef ACTIVE_RESPONSE
896         else if(!strcasecmp(stoks[0], "max_active_responses"))
897         {
898             if (stoks[1])
899             {
900                 config->max_active_responses = (uint8_t)SnortStrtoulRange(stoks[1], &endPtr, 10, 0, STREAM_MAX_ACTIVE_RESPONSES_MAX);
901             }
902             if ((!stoks[1] || (endPtr == &stoks[1][0])) || *endPtr ||
903                     (config->max_active_responses > STREAM_MAX_ACTIVE_RESPONSES_MAX))
904             {
905                 FatalError("%s(%d) => 'max_active_responses %d' invalid: "
906                         "value must be between 0 and %d responses.\n",
907                         file_name, file_line, config->max_active_responses,
908                         STREAM_MAX_ACTIVE_RESPONSES_MAX);
909             }
910             if ( config->max_active_responses > 0 )
911             {
912                 Active_SetEnabled(2);
913             }
914         }
915         else if(!strcasecmp(stoks[0], "min_response_seconds"))
916         {
917             if (stoks[1])
918             {
919                 config->min_response_seconds = strtoul(stoks[1], &endPtr, 10);
920             }
921             if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
922             {
923                 FatalError("%s(%d) => Invalid min_response_seconds in config file. "
924                         " Requires integer parameter.\n", file_name, file_line);
925             }
926             else if ( ( config->min_response_seconds > STREAM_MIN_RESPONSE_SECONDS_MAX ) ||
927                     ( config->min_response_seconds < 1 ) )
928             {
929                 FatalError("%s(%d) => 'min_response_seconds %d' invalid: "
930                         "value must be between 1 and %d seconds.\n",
931                         file_name, file_line, config->min_response_seconds,
932                         STREAM_MIN_RESPONSE_SECONDS_MAX);
933             }
934         }
935 #endif
936 #ifdef ENABLE_HA
937         else if (!strcasecmp(stoks[0], "enable_ha"))
938         {
939             if (s_toks > 1) //Trailing parameters
940             {
941                 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
942                         file_name, file_line);
943             }
944             config->enable_ha = 1;
945         }
946 #endif /* ENABLE_HA */
947         else if(!strcasecmp(stoks[0], "disabled"))
948         {
949             if (s_toks > 1) //Trailing parameters
950             {
951                 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
952                         file_name, file_line);
953             }
954             config->disabled = 1;
955 #if 0
956             // TBD-EDM - breaks reg tests, enable after merge and fix tests
957             WarningMessage("%s(%d) Session disable option is set...supported option but nothing useful can come of this.\n",
958                     file_name, file_line);
959 #endif
960         }
961         else
962         {
963             FatalError("%s(%d) => Unknown Session global option (%s)\n",
964                     file_name, file_line, toks[i]);
965         }
966 
967         mSplitFree(&stoks, s_toks);
968     }
969 
970     mSplitFree(&toks, num_toks);
971 }
972 
printSessionConfiguration(SessionConfiguration * config)973 static void printSessionConfiguration(SessionConfiguration *config)
974 {
975 // TBD-EDM
976 #if 0
977     if (config == NULL)
978         return;
979 
980     LogMessage("Session global config:\n");
981     if (config->track_tcp_sessions == STREAM_TRACK_YES)
982         LogMessage("    Max TCP sessions: %u\n", config->max_tcp_sessions);
983     if (config->track_udp_sessions == STREAM_TRACK_YES)
984         LogMessage("    Max UDP sessions: %u\n", config->max_udp_sessions);
985     if (config->track_icmp_sessions == STREAM_TRACK_YES)
986         LogMessage("    Max ICMP sessions: %u\n", config->max_icmp_sessions);
987     if (config->track_ip_sessions == STREAM_TRACK_YES)
988         LogMessage("    Max IP sessions: %u\n", config->max_ip_sessions);
989     if (config->prune_log_max)
990     {
991         LogMessage("    Log info if session memory consumption exceeds %d\n",
992                 config->prune_log_max);
993     }
994 #ifdef ACTIVE_RESPONSE
995     LogMessage("    Send up to %d active responses\n", config->max_active_responses);
996 
997     if (config->max_active_responses > 1)
998     {
999         LogMessage("    Wait at least %d seconds between responses\n", config->min_response_seconds);
1000     }
1001 #endif
1002 #ifdef ENABLE_HA
1003     LogMessage("    High Availability: %s\n", config->enable_ha ? "ENABLED" : "DISABLED");
1004 #endif
1005 #endif
1006 }
1007 
resetSessionState(int signal,void * foo)1008 static void resetSessionState( int signal, void *foo )
1009 {
1010     if ( session_configuration == NULL )
1011         return;
1012 
1013     mempool_clean( &sessionFlowMempool );
1014 }
1015 
resetSessionStatistics(int signal,void * foo)1016 static void resetSessionStatistics( int signal, void *foo )
1017 {
1018     memset( &session_stats, 0, sizeof( session_stats ) );
1019 #ifdef ENABLE_HA
1020     SessionResetHAStats();
1021 #endif
1022 }
1023 
exitSessionCleanly(int signal,void * foo)1024 static void exitSessionCleanly( int signal, void *foo )
1025 {
1026 #ifdef ENABLE_HA
1027     SessionCleanHA();
1028 #endif
1029 
1030     /* free expected session data structures... */
1031     StreamExpectCleanup();
1032 
1033     mempool_destroy( &sessionFlowMempool );
1034     freeSessionPlugins( );
1035     SessionFreeConfig( session_configuration );
1036     session_configuration = NULL;
1037 }
1038 
verifySessionConfig(struct _SnortConfig * sc)1039 static int verifySessionConfig( struct _SnortConfig *sc )
1040 {
1041     int obj_size = 0;
1042     unsigned total_sessions = 0;
1043 
1044     if( session_configuration == NULL )
1045     {
1046         FatalError("%s(%d) Session config is NULL.\n", __FILE__, __LINE__);
1047     }
1048 
1049 #ifdef ENABLE_HA
1050     if( session_configuration->enable_ha )
1051     {
1052         if( ( SessionVerifyHAConfig( sc, session_configuration->ha_config ) != 0 ) )
1053         {
1054             FatalError( "Session HA misconfigured.  Session preprocessor exiting\n" );
1055         }
1056     }
1057 #endif
1058 
1059     if(session_configuration->track_tcp_sessions)
1060        total_sessions += session_configuration->max_tcp_sessions;
1061     else
1062     {
1063         session_configuration->memcap = 0;
1064         session_configuration->max_tcp_sessions = 0;
1065     }
1066     if(session_configuration->track_udp_sessions)
1067        total_sessions += session_configuration->max_udp_sessions;
1068     else
1069         session_configuration->max_udp_sessions = 0;
1070     if(session_configuration->track_icmp_sessions)
1071        total_sessions += session_configuration->max_icmp_sessions;
1072     else
1073         session_configuration->max_icmp_sessions = 0;
1074     if(session_configuration->track_ip_sessions)
1075        total_sessions += session_configuration->max_ip_sessions;
1076     else
1077         session_configuration->max_ip_sessions = 0;
1078 
1079     if( total_sessions == 0 && !session_configuration->disabled)
1080     {
1081         FatalError( "%s(%d) All protocols configured with 0 as max session count.\n", __FILE__, __LINE__ );
1082     }
1083 
1084     /* Initialize the memory pool for Flowbits Data */
1085     /* use giFlowbitSize - 1, since there is already 1 byte in the
1086      * StreamFlowData structure */
1087     obj_size = sizeof( StreamFlowData ) + getFlowbitSizeInBytes( ) - 1;
1088 
1089     if( ( obj_size % sizeof( long ) ) != 0 )
1090     {
1091         /* Increase obj_size by sizeof(long) to force sizeof(long) byte
1092          * alignment for each object in the mempool.  Without this,
1093          * the mempool data buffer was not aligned. Overlaying the
1094          * StreamFlowData structure caused problems on some Solaris
1095          * platforms. */
1096         obj_size += ( sizeof( long ) - ( obj_size % sizeof( long ) ) );
1097     }
1098 
1099     if (total_sessions != 0)
1100     {
1101         if( mempool_init( &sessionFlowMempool, total_sessions, obj_size ) != 0 )
1102         {
1103             FatalError( "%s(%d) Could not initialize flow bits memory pool.\n", __FILE__, __LINE__ );
1104         }
1105     }
1106 
1107     session_configuration->max_sessions = total_sessions;
1108     session_configuration->numSnortPolicies = sc->num_policies_allocated;
1109     session_configuration->policy_ref_count = SnortPreprocAlloc( sc->num_policies_allocated,
1110                                                 sizeof( uint32_t ), PP_STREAM,
1111                                                 PP_MEM_CATEGORY_CONFIG );
1112     if( !session_configuration->policy_ref_count )
1113     {
1114         FatalError( "%s(%d) Could not allocate policy ref count.\n", __FILE__, __LINE__ );
1115     }
1116 
1117     return 0;
1118 }
1119 
printSessionStatistics(int exiting)1120 static void printSessionStatistics( int exiting )
1121 {
1122 #if 0
1123     LogMessage("Session statistics:\n");
1124     LogMessage("            Total sessions: %u\n", session_stats.total_tcp_sessions +
1125             session_stats.total_udp_sessions +
1126             session_stats.total_icmp_sessions +
1127             session_stats.total_ip_sessions);
1128     LogMessage("              TCP sessions: %u\n", session_stats.total_tcp_sessions);
1129     LogMessage("              UDP sessions: %u\n", session_stats.total_udp_sessions);
1130     LogMessage("             ICMP sessions: %u\n", session_stats.total_icmp_sessions);
1131     LogMessage("               IP sessions: %u\n", session_stats.total_ip_sessions);
1132 
1133     LogMessage("                    Events: %u\n", session_stats.events);
1134     LogMessage("           Internal Events: %u\n", session_stats.internalEvents);
1135     LogMessage("           TCP Port Filter\n");
1136     LogMessage("                   Dropped: %u\n", session_stats.tcp_port_filter.filtered);
1137     LogMessage("                 Inspected: %u\n", session_stats.tcp_port_filter.inspected);
1138     LogMessage("                   Tracked: %u\n", session_stats.tcp_port_filter.session_tracked);
1139     LogMessage("           UDP Port Filter\n");
1140     LogMessage("                   Dropped: %u\n", session_stats.udp_port_filter.filtered);
1141     LogMessage("                 Inspected: %u\n", session_stats.udp_port_filter.inspected);
1142     LogMessage("                   Tracked: %u\n", session_stats.udp_port_filter.session_tracked);
1143 #ifdef ENABLE_HA
1144     SessionPrintHAStats();
1145 #endif
1146 #endif
1147 }
1148 
initPreprocDispatchList(Packet * p)1149 static void initPreprocDispatchList(  Packet *p )
1150 {
1151     PreprocEvalFuncNode *ppn;
1152     SnortPolicy *policy = snort_conf->targeted_policies[ getNapRuntimePolicy() ];
1153 
1154     // set initial post session preproc enabled for the policy selected for
1155     // this session
1156     ppn = policy->preproc_eval_funcs;
1157     while( ppn != NULL && ppn->priority <= PP_SESSION_PRIORITY )
1158         ppn = ppn->next;
1159 
1160     p->cur_pp = ppn;
1161 }
1162 
isPacketEligible(Packet * p)1163 static inline int isPacketEligible( Packet *p )
1164 {
1165     if( ( p->frag_flag ) || ( p->error_flags & PKT_ERR_CKSUM_IP ) )
1166         return 0;
1167 
1168     if( p->packet_flags & PKT_REBUILT_STREAM )
1169         return 0;
1170 
1171     if( !IPH_IS_VALID( p ) )
1172         return 0;
1173 
1174     switch( GET_IPH_PROTO( p ) )
1175     {
1176         case IPPROTO_TCP:
1177             {
1178                 if( p->tcph == NULL )
1179                     return 0;
1180 
1181                 if( p->error_flags & PKT_ERR_CKSUM_TCP )
1182                     return 0;
1183             }
1184             break;
1185 
1186         case IPPROTO_UDP:
1187             {
1188                 if( p->udph == NULL )
1189                     return 0;
1190 
1191                 if( p->error_flags & PKT_ERR_CKSUM_UDP )
1192                     return 0;
1193             }
1194             break;
1195 
1196         case IPPROTO_ICMP:
1197         case IPPROTO_ICMPV6:
1198             {
1199                 if( p->icmph == NULL )
1200                     return 0;
1201 
1202                 if( p->error_flags & PKT_ERR_CKSUM_ICMP )
1203                     return 0;
1204             }
1205             break;
1206 
1207         default:
1208             if( p->iph == NULL )
1209                 return 0;
1210             break;
1211     }
1212 
1213     return 1;
1214 }
1215 
insertIntoOneWaySessionList(SessionCache * session_cache,SessionControlBlock * scb)1216 void insertIntoOneWaySessionList( SessionCache *session_cache, SessionControlBlock *scb )
1217 {
1218 
1219     if( session_cache->ows_list.head == NULL )
1220     {
1221         // list is empty link head & tail pointers to this scb
1222         session_cache->ows_list.head = scb;
1223         session_cache->ows_list.tail = scb;
1224         scb->ows_next = NULL;
1225         scb->ows_prev = NULL;
1226     }
1227     else
1228     {
1229         // list is not empty, add this node to the end
1230         session_cache->ows_list.tail->ows_next = scb;
1231         scb->ows_prev = session_cache->ows_list.tail;
1232         scb->ows_next = NULL;
1233         session_cache->ows_list.tail = scb;
1234     }
1235 
1236     // set scb state to in oneway list and increment count of sessions
1237     // in the oneway list
1238     scb->in_oneway_list = true;
1239     session_cache->ows_list.num_sessions++;
1240 }
1241 
removeFromOneWaySessionList(SessionCache * session_cache,SessionControlBlock * scb)1242 void removeFromOneWaySessionList( SessionCache *session_cache, SessionControlBlock *scb )
1243 {
1244     if( scb->ows_prev == NULL )
1245     {
1246         // removing first node
1247         if( scb->ows_next == NULL )
1248         {
1249             // only node in list
1250             session_cache->ows_list.head = NULL;
1251             session_cache->ows_list.tail = NULL;
1252         }
1253         else
1254         {
1255             session_cache->ows_list.head = scb->ows_next;
1256             scb->ows_next->ows_prev = NULL;
1257         }
1258     }
1259     else if ( scb->ows_next == NULL )
1260     {
1261         // removing last node ( list with one node detected above so must be >1 nodes here )
1262         session_cache->ows_list.tail = scb->ows_prev;
1263         scb->ows_prev->ows_next = NULL;
1264     }
1265     else
1266     {
1267         // removing node from middle of list
1268         scb->ows_prev->ows_next = scb->ows_next;
1269         scb->ows_next->ows_prev = scb->ows_prev;
1270     }
1271 
1272     scb->ows_next = NULL;
1273     scb->ows_prev = NULL;
1274 
1275     // set scb state to not in oneway list and decrement count of sessions
1276     // in the oneway list
1277     scb->in_oneway_list = false;
1278     session_cache->ows_list.num_sessions--;
1279 }
1280 
decrementPolicySessionRefCount(SessionControlBlock * scb)1281 static void decrementPolicySessionRefCount( SessionControlBlock *scb )
1282 {
1283 
1284 #ifdef ENABLE_HA
1285     // if in standby no policy bound to this session
1286     if( scb->ha_flags & HA_FLAG_STANDBY )
1287         return;
1288 #endif
1289 
1290     if( scb->napPolicyId < scb->session_config->numSnortPolicies )
1291     {
1292         scb->session_config->policy_ref_count[ scb->napPolicyId ]--;
1293 
1294 #ifdef SNORT_RELOAD
1295         if( scb->session_config != session_configuration ||
1296                 scb->session_config->no_ref_cb )
1297 #else
1298         if( scb->session_config != session_configuration )
1299 #endif
1300         {
1301             uint32_t i;
1302             bool no_refs = true;
1303 
1304             for( i = 0; i < scb->session_config->numSnortPolicies; i++ )
1305                 if( scb->session_config->policy_ref_count[ i ] > 0 )
1306                 {
1307                     no_refs = false;
1308                    break;
1309                 }
1310 
1311            if( no_refs )
1312            {
1313 #ifdef SNORT_RELOAD
1314                if( scb->session_config->no_ref_cb )
1315                {
1316                     scb->session_config->no_ref_cb(scb->session_config->no_ref_cb_data);
1317                     scb->session_config->no_ref_cb = NULL;
1318                     scb->session_config->no_ref_cb_data = NULL;
1319                }
1320 #endif
1321                if( scb->session_config != session_configuration )
1322                    SessionFreeConfig( scb->session_config );
1323            }
1324         }
1325     }
1326     else
1327     {
1328         WarningMessage("%s(%d) NAP Policy ID is UNBOUND or not valid: %u", file_name, file_line, scb->napPolicyId );
1329     }
1330 }
1331 
initializePacketPolicy(Packet * p,SessionControlBlock * scb)1332 void initializePacketPolicy( Packet *p, SessionControlBlock *scb )
1333 {
1334     SnortPolicy *policy;
1335 
1336     // opensource policy selector will set to true, product does not
1337     p->ips_os_selected = false;
1338 
1339     if( scb != NULL )
1340     {
1341         // if config pointer is same as online we are good to go...
1342         if( scb->session_config != session_configuration )
1343         {
1344             // session config has been reloaded, reevaluate packet against NAP rules
1345             decrementPolicySessionRefCount( scb );
1346             scb->initial_pp = NULL;
1347             scb->stream_config_stale = true;
1348             scb->napPolicyId = SF_POLICY_UNBOUND;
1349             scb->ipsPolicyId = SF_POLICY_UNBOUND;
1350             scb->session_config = session_configuration;
1351         }
1352 
1353         /* Select the policy for this session...Then initialize list of
1354          * additional preprocs to be dispatched for this session
1355          */
1356         if ( scb->napPolicyId == SF_POLICY_UNBOUND )
1357         {
1358             if( isNapRuntimePolicyDefault())
1359                 getSessionPlugins()->select_session_nap( p,
1360                         ( getPacketDirection( p ) & PKT_FROM_CLIENT ) ? true : false );
1361             scb->napPolicyId = getNapRuntimePolicy();
1362             session_configuration->policy_ref_count[ scb->napPolicyId ]++;
1363             scb->ipsPolicyId = getIpsRuntimePolicy();
1364 
1365             // set the preproc enable mask for pps registered to handle traffic on this port
1366             policy = snort_conf->targeted_policies[ scb->napPolicyId ];
1367             scb->enabled_pps = policy->pp_enabled[ ntohs(scb->server_port) ];
1368             if( scb->port_guess )
1369                 scb->enabled_pps |= policy->pp_enabled[ ntohs(scb->client_port) ];
1370             scb->ips_os_selected = p->ips_os_selected;
1371         }
1372         else
1373         {
1374             // set runtime policy from session setting, session already has preproc list
1375             setNapRuntimePolicy( scb->napPolicyId );
1376             setIpsRuntimePolicy( scb->ipsPolicyId );
1377             p->ips_os_selected = scb->ips_os_selected;
1378         }
1379 
1380         initPreprocDispatchList( p );
1381         EnablePreprocessors( p, scb->enabled_pps );
1382 
1383         // save current ha state for ha processing after packet processing has completed
1384         scb->cached_ha_state = scb->ha_state;
1385     }
1386     else
1387     {
1388         // no session, select policy from packet network parameters
1389         getSessionPlugins()->select_session_nap( p,
1390                                                  ( getPacketDirection( p ) & PKT_FROM_CLIENT ) ? true : false );
1391         initPreprocDispatchList( p );
1392         policy = snort_conf->targeted_policies[ getNapRuntimePolicy() ];
1393         EnablePreprocessors( p, policy->pp_enabled[ p->dp ] | policy->pp_enabled[ p->sp ] );
1394     }
1395 }
1396 
findPacketSessionControlBlock(SessionCache * sessionCache,Packet * p,SessionKey * key)1397 static inline SessionControlBlock *findPacketSessionControlBlock(SessionCache *sessionCache, Packet *p, SessionKey *key)
1398 {
1399     SessionControlBlock *scb = NULL;
1400 #if defined(DAQ_CAPA_CST_TIMEOUT)
1401         uint64_t timeout;
1402 #endif
1403 
1404     if (!sessionCache)
1405         return NULL;
1406     scb = checkSessionControlBlock(sessionCache, p, key);
1407     if (scb && getSessionExpirationTime(p, scb))
1408     {
1409         // We retrieved a scb which has already expired but not deleted
1410         // Delete the previous scb and recover  it from HA data
1411         deleteSessionByKey (scb, "expired and not cleaned") ;
1412         scb = p->ssnptr = NULL;
1413     }
1414 #if defined(DAQ_CAPA_CST_TIMEOUT)
1415     else if (scb && (p->pkth->flags & DAQ_PKT_FLAG_NEW_FLOW))
1416     {
1417         //We retrieved a scb but this is a new flow, which means this is stale scb, Delete it
1418         deleteSessionByKey (scb, "stale and not cleaned") ;
1419         scb = p->ssnptr = NULL;
1420     }
1421 #endif
1422     else
1423     {
1424         // Update the time of last data seen in the SCB
1425         updateSessionControlBlockTime(scb, p);
1426     }
1427 
1428 #if defined(ENABLE_HA) && defined(HAVE_DAQ_QUERYFLOW)
1429     if ((!scb || !scb->appDataList) && session_configuration->enable_ha && session_configuration->ha_config->use_daq &&
1430 #ifndef REG_TEST
1431             (p->pkth->flags & DAQ_PKT_FLAG_HA_STATE_AVAIL) &&
1432 #endif
1433              SessionHAQueryDAQState(p->pkth) == 0)
1434     {
1435 
1436         scb = getSessionControlBlock(sessionCache, p, key);
1437 #if defined(DAQ_CAPA_CST_TIMEOUT)
1438         if (scb && Daq_Capa_Timeout)
1439         {
1440           GetTimeout(p,&timeout);
1441           sessionCache->timeoutNominal = timeout;
1442           setSessionExpirationTime(p,scb,timeout);
1443     }
1444 #endif
1445     }
1446 #endif
1447 
1448 #ifdef HAVE_DAQ_PKT_TRACE
1449     if (pkt_trace_enabled && (p->pkth->flags & DAQ_PKT_FLAG_SIMULATED) && scb)
1450     {
1451         addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
1452             "Session: simulated packet matches existing snort session\n"));
1453     }
1454 #endif
1455 
1456     return scb;
1457 }
1458 
1459 // Return true if a preprocessor is enabled for a session
isPreprocEnabledForSession(SessionControlBlock * scb,uint32_t preproc_id)1460 static inline bool isPreprocEnabledForSession( SessionControlBlock *scb, uint32_t preproc_id )
1461 {
1462 	return  ( scb && scb->enabled_pps & (UINT64_C(1) << preproc_id) ) ? true : false;
1463 }
1464 
1465 // Turn ON a preprocessor for a session
enablePreprocForSession(SessionControlBlock * scb,uint32_t preproc_id)1466 static inline void enablePreprocForSession( SessionControlBlock *scb, uint32_t preproc_id)
1467 {
1468     if( scb != NULL )
1469         scb->enabled_pps |= ( UINT64_C(1) << preproc_id );
1470 }
1471 
1472 #if defined (HAVE_DAQ_QUERYFLOW) && defined (DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID)
SessionConnMetaQuery(const DAQ_PktHdr_t * pkthdr)1473 int SessionConnMetaQuery(const DAQ_PktHdr_t *pkthdr)
1474 {
1475     DAQ_QueryFlow_t query;
1476     int rval;
1477 
1478     query.type = DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID;
1479     query.length = 0;
1480     query.value = 0;
1481 
1482     rval = DAQ_QueryFlow(pkthdr, &query);
1483     if (rval == DAQ_SUCCESS ||
1484         rval == DAQ_ERROR_NOTSUP)
1485         return 1;
1486     else
1487         return 0;
1488 }
1489 #endif
1490 
sessionPacketProcessor(Packet * p,void * context)1491 static void sessionPacketProcessor(Packet *p, void *context)
1492 {
1493     SessionControlBlock *scb = NULL;
1494     SessionKey key;
1495     uint32_t flags;
1496 #if defined(DAQ_CAPA_CST_TIMEOUT)
1497     uint64_t timeout;
1498 #endif
1499 
1500     PROFILE_VARS;
1501 
1502     if (!firstPacketTime)
1503         firstPacketTime = p->pkth->ts.tv_sec;
1504 
1505     if( !isPacketEligible( p ) )
1506     {
1507         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "Is not eligible!\n"););
1508         initializePacketPolicy( p, p->ssnptr );
1509         return;
1510     }
1511 
1512     DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"););
1513     DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "In Session!\n"););
1514 
1515     PREPROC_PROFILE_START(sessionPerfStats);
1516 
1517     if( p->ssnptr == NULL )
1518     {
1519         switch( GET_IPH_PROTO( p ) )
1520         {
1521             case IPPROTO_TCP:
1522                 scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_TCP ], p, &key );
1523 #if defined(DAQ_CAPA_CST_TIMEOUT)
1524                 /* we will do syn re-evaluation when the we recive SYN for stale scssions
1525                  * we will delete session when we recive SYN on session
1526                  * which is going to be exired in this time STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED*/
1527                 if ( scb != NULL  &&
1528                   Daq_Capa_Timeout &&  (p->tcph  && p->tcph->th_flags & (TH_SYN)) &&
1529                   (scb->expire_time - (((uint64_t)p->pkth->ts.tv_sec ) * TCP_HZ) <= STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED))
1530                 {
1531                   scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
1532                   deleteSession(proto_session_caches[ SESSION_PROTO_TCP ], scb, "stale/timeout",true);
1533                   scb = NULL;
1534                 }
1535 #endif
1536                 if ( ( scb == NULL ) && SessionTrackingEnabled( session_configuration, SESSION_PROTO_TCP ) )
1537                 {
1538 #if defined(HAVE_DAQ_QUERYFLOW) && defined (DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID)
1539                     /* It is observed for non-IP packets, conn meta check fails. In case of conn meta check failure,
1540                      * check if non_ip_pkt is set to allow flow creation.
1541                      */
1542                     if (SessionConnMetaQuery(p->pkth) || p->non_ip_pkt) {
1543                         scb = createSession( proto_session_caches[ SESSION_PROTO_TCP ], p, &key );
1544                     } else {
1545                         if (pkt_trace_enabled)
1546                             addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
1547                                         "Conn meta is not available. So not creating TCP session\n"));
1548                         DisablePacketAnalysis( p );
1549                         PREPROC_PROFILE_END(sessionPerfStats);
1550                         return;
1551                     }
1552 #else
1553                     scb = createSession( proto_session_caches[ SESSION_PROTO_TCP ], p, &key );
1554 #endif
1555 #if defined(DAQ_CAPA_CST_TIMEOUT)
1556                     if (Daq_Capa_Timeout && scb != NULL)
1557                     {
1558 
1559                       GetTimeout(p,&timeout);
1560                       timeout = timeout + STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED;
1561                       proto_session_caches[ SESSION_PROTO_TCP ]->timeoutNominal = timeout;
1562                       setSessionExpirationTime(p,scb,timeout);
1563                     }
1564 #endif
1565                 }
1566 
1567                 if( ( scb != NULL ) && !scb->session_established && ( getSessionPlugins()->set_tcp_dir_ports != NULL ) )
1568                     getSessionPlugins()->set_tcp_dir_ports( p, scb );
1569 
1570                 break;
1571 
1572             case IPPROTO_UDP:
1573                 scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_UDP ], p, &key );
1574 				if( ( scb == NULL ) &&  SessionTrackingEnabled( session_configuration, SESSION_PROTO_UDP ) )
1575 				{
1576 #if defined(HAVE_DAQ_QUERYFLOW) && defined (DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID)
1577                     /* It is observed for non-IP packets, conn meta check fails. In case of conn meta check failure,
1578                      * check if non_ip_pkt is set to allow flow creation.
1579                      */
1580                     if (SessionConnMetaQuery(p->pkth) || p->non_ip_pkt) {
1581                         scb = createSession( proto_session_caches[ SESSION_PROTO_UDP ], p, &key );
1582                     } else {
1583                         if (pkt_trace_enabled)
1584                             addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
1585                                         "Conn meta is not available. So not creating UDP session\n"));
1586                         DisablePacketAnalysis( p );
1587                         PREPROC_PROFILE_END(sessionPerfStats);
1588                         return;
1589                     }
1590 #else
1591                     scb = createSession( proto_session_caches[ SESSION_PROTO_UDP ], p, &key );
1592 #endif
1593 #if defined(DAQ_CAPA_CST_TIMEOUT)
1594                     if (Daq_Capa_Timeout && scb != NULL)
1595                     {
1596                         GetTimeout(p,&timeout);
1597                         proto_session_caches[ SESSION_PROTO_UDP ]->timeoutNominal = timeout;
1598                         setSessionExpirationTime(p,scb,timeout);
1599                 }
1600 #endif
1601                 }
1602 
1603                 if( scb && !scb->session_established && ( getSessionPlugins()->set_udp_dir_ports != NULL ) )
1604                     getSessionPlugins()->set_udp_dir_ports( p, scb );
1605 
1606                 break;
1607 
1608             case IPPROTO_ICMP:
1609                 // new flow allocate an scb, if not tracking ICMP, then fall thru and treat packet as
1610                 // an IP protocol packet
1611                 if ( SessionTrackingEnabled( session_configuration, SESSION_PROTO_ICMP ) )
1612                 {
1613                     scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_ICMP ], p, &key );
1614                     if( scb != NULL )
1615                     break;
1616 
1617                     scb = createSession( proto_session_caches[ SESSION_PROTO_ICMP ], p, &key );
1618 #if defined(DAQ_CAPA_CST_TIMEOUT)
1619                     if (Daq_Capa_Timeout && scb != NULL)
1620                     {
1621 
1622                       GetTimeout(p,&timeout);
1623                       proto_session_caches[ SESSION_PROTO_ICMP ]->timeoutNominal = timeout;
1624                       setSessionExpirationTime(p,scb,timeout);
1625                     }
1626 #endif
1627 
1628                     break;
1629                 }
1630                 // fall thru, not tracking ICMP, treat as IP packet...
1631 
1632             case IPPROTO_IP:
1633             default:
1634                 scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_IP ], p, &key );
1635                 if( ( scb == NULL ) && SessionTrackingEnabled( session_configuration, SESSION_PROTO_IP ) )
1636                 {
1637                     scb = createSession( proto_session_caches[ SESSION_PROTO_IP ], p, &key );
1638 #if defined(DAQ_CAPA_CST_TIMEOUT)
1639                     if (Daq_Capa_Timeout && scb != NULL)
1640                     {
1641 
1642                       GetTimeout(p,&timeout);
1643                       proto_session_caches[ SESSION_PROTO_IP ]->timeoutNominal = timeout;
1644                       setSessionExpirationTime(p,scb,timeout);
1645                     }
1646 #endif
1647                 }
1648                 break;
1649 
1650         }
1651         // assign allocated SCB to the Packet structure
1652         p->ssnptr = scb;
1653     }
1654     else
1655     {
1656         scb = p->ssnptr;
1657     }
1658 
1659     initializePacketPolicy( p, scb );
1660 
1661     flags = getSessionFlags( scb );
1662 
1663     if( ( scb && (getIPRepUpdateCount() != scb->iprep_update_counter ) )
1664         && ( !(isPreprocEnabledForSession(scb,PP_REPUTATION)) && !(flags & (SSNFLAG_DETECTION_DISABLED|SSNFLAG_FORCE_BLOCK)) ) )
1665     {
1666 	// If preproc was disabled or flow was whitelisted earlier, re-enable reputation
1667         EnablePreprocessor(p, PP_REPUTATION);
1668         enablePreprocForSession(scb, PP_REPUTATION);
1669         scb->ha_state.session_flags &= ~SSNFLAG_DETECTION_DISABLED;
1670         scb->ha_state.session_flags &= ~SSNFLAG_FORCE_BLOCK;
1671     }
1672     else if( flags & SSNFLAG_FORCE_BLOCK )
1673     {
1674         DisablePacketAnalysis( p );
1675         /* Detect will turn on the perfmonitor preprocessor when this function returns */
1676         scb->enabled_pps = PP_PERFMONITOR;
1677         Active_ForceDropSession();
1678         if (pkt_trace_enabled)
1679             addPktTraceData(VERDICT_REASON_SESSION, snprintf(trace_line, MAX_TRACE_LINE,
1680                 "Session: blocked session flag is true, %s\n", getPktTraceActMsg()));
1681         else addPktTraceData(VERDICT_REASON_SESSION, 0);
1682     }
1683     else if( flags & SSNFLAG_DETECTION_DISABLED )
1684     {
1685         DisablePacketAnalysis( p );
1686         /* Detect will turn on the perfmonitor preprocessor when this function returns */
1687         scb->enabled_pps = PP_PERFMONITOR;
1688     }
1689 
1690     PREPROC_PROFILE_END(sessionPerfStats);
1691 }
1692 
1693 /*************************** API Implementations *******************/
1694 #define SESSION_CACHE_FLAG_PURGING  0x01
1695 #define SESSION_CACHE_FLAG_PRUNING  0x02
1696 
1697 #if 0
1698 
1699 void PrintSessionKey(SessionKey *skey)
1700 {
1701     LogMessage("SessionKey:\n");
1702     LogMessage("      ip_l     = 0x%08X\n", skey->ip_l);
1703     LogMessage("      ip_h     = 0x%08X\n", skey->ip_h);
1704     LogMessage("      prt_l    = %d\n", skey->port_l);
1705     LogMessage("      prt_h    = %d\n", skey->port_h);
1706     LogMessage("      vlan_tag = %d\n", skey->vlan_tag);
1707 #ifdef MPLS
1708     LogMessage("    mpls label = 0x%08X\n", skey->mplsLabel);
1709 #endif
1710 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1711     LogMessage(" addr space id = %d\n", skey->addressSpaceId);
1712 #endif
1713 }
1714 #endif
1715 
getActiveSessionCount(SessionCache * session_cache)1716 static int getActiveSessionCount(SessionCache* session_cache)
1717 {
1718     if (session_cache &&session_cache->hashTable)
1719         return session_cache->hashTable->count;
1720     else
1721         return 0;
1722 }
1723 
getSessionPruneCount(uint32_t protocol)1724 static uint32_t getSessionPruneCount( uint32_t protocol )
1725 {
1726 
1727     if( protocol < SESSION_PROTO_MAX )
1728     {
1729         if( proto_session_caches[ protocol ] )
1730             return proto_session_caches[ protocol ]->prunes;
1731         else
1732             return 0;
1733     }
1734     else
1735     {
1736         WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
1737         return 0;
1738     }
1739 }
1740 
resetSessionPruneCount(uint32_t protocol)1741 static void resetSessionPruneCount( uint32_t protocol )
1742 {
1743     if( protocol < SESSION_PROTO_MAX )
1744     {
1745         if( proto_session_caches[protocol] )
1746             proto_session_caches[protocol]->prunes = 0;
1747     }
1748     else
1749     {
1750         WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
1751     }
1752 }
1753 
initSessionKeyFromPktHeader(sfaddr_t * srcIP,uint16_t srcPort,sfaddr_t * dstIP,uint16_t dstPort,char proto,uint16_t vlan,uint32_t mplsId,uint16_t addressSpaceId,uint32_t carrierId,SessionKey * key)1754 static int initSessionKeyFromPktHeader( sfaddr_t* srcIP,
1755         uint16_t srcPort,
1756         sfaddr_t* dstIP,
1757         uint16_t dstPort,
1758         char proto,
1759         uint16_t vlan,
1760         uint32_t mplsId,
1761 #if !defined(DAQ_CAPA_VRF) || defined(SFLINUX)
1762         uint16_t addressSpaceId,
1763 #else
1764         uint16_t address_space_id_src,
1765         uint16_t address_space_id_dst,
1766 #endif
1767 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
1768         uint32_t carrierId,
1769 #endif
1770         SessionKey *key )
1771 
1772 {
1773     uint16_t sport;
1774     uint16_t dport;
1775     sfaddr_t *src;
1776     sfaddr_t *dst;
1777     /* Because the key is going to be used for hash lookups,
1778      * the lower of the values of the IP address field is
1779      * stored in the key->ip_l and the port for that ip is
1780      * stored in key->port_l.
1781      */
1782 
1783     if (!key)
1784         return 0;
1785 
1786 
1787     switch (proto)
1788     {
1789         case IPPROTO_TCP:
1790         case IPPROTO_UDP:
1791             sport = srcPort;
1792             dport = dstPort;
1793             break;
1794         case IPPROTO_ICMP:
1795             if (srcPort == ICMP_ECHOREPLY)
1796             {
1797                 dport = ICMP_ECHO; /* Treat ICMP echo reply the same as request */
1798                 sport = 0;
1799             }
1800             else if (srcPort == ICMP_ROUTER_ADVERTISE)
1801             {
1802                 dport = ICMP_ROUTER_SOLICIT; /* Treat ICMP router advertisement the same as solicitation */
1803                 sport = 0;
1804                 srcIP = &fixed_addr; /* Matching src address to solicit dest address */
1805             }
1806             else /* otherwise, every ICMP type gets different key */
1807             {
1808                 sport = srcPort;
1809                 dport = 0;
1810                 if (srcPort == ICMP_ROUTER_SOLICIT)
1811                     dstIP = &fixed_addr; /* To get unique key, don't use multicast/broadcast addr (RFC 1256) */
1812             }
1813             break;
1814         case IPPROTO_ICMPV6:
1815             if (srcPort == ICMP6_REPLY)
1816             {
1817                 dport = ICMP6_ECHO; /* Treat ICMPv6 echo reply the same as request */
1818                 sport = 0;
1819             }
1820             else if (srcPort == ICMP6_ADVERTISEMENT)
1821             {
1822                 dport = ICMP6_SOLICITATION; /* Treat ICMPv6 router advertisement the same as solicitation */
1823                 sport = 0;
1824                 srcIP = &fixed_addr; /* Matching src address to solicit dest address */
1825             }
1826             else /* otherwise, every ICMP type gets different key */
1827             {
1828                 sport = srcPort;
1829                 dport = 0;
1830                 if (srcPort == ICMP6_SOLICITATION)
1831                     dstIP = &fixed_addr; /* To get unique key, don't use multicast addr (RFC 4861) */
1832             }
1833             break;
1834         default:
1835             sport = dport = 0;
1836             break;
1837     }
1838 
1839     src = srcIP;
1840     dst = dstIP;
1841 
1842     if (sfip_fast_lt6(src, dst))
1843     {
1844         COPY4(key->ip_l, sfaddr_get_ip6_ptr(src));
1845         key->port_l = sport;
1846 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1847         key->addressSpaceId_l = address_space_id_src;
1848         key->addressSpaceId_h = address_space_id_dst;
1849 #endif
1850         COPY4(key->ip_h, sfaddr_get_ip6_ptr(dst));
1851         key->port_h = dport;
1852     }
1853     else if (sfip_fast_eq6(src, dst))
1854     {
1855         COPY4(key->ip_l, sfaddr_get_ip6_ptr(src));
1856         COPY4(key->ip_h, sfaddr_get_ip6_ptr(dst));
1857         if (sport < dport)
1858         {
1859             key->port_l = sport;
1860             key->port_h = dport;
1861 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1862             key->addressSpaceId_l = address_space_id_src;
1863             key->addressSpaceId_h = address_space_id_dst;
1864 #endif
1865         }
1866         else
1867         {
1868             key->port_l = dport;
1869             key->port_h = sport;
1870 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1871             key->addressSpaceId_l = address_space_id_dst;
1872             key->addressSpaceId_h = address_space_id_src;
1873 #endif
1874         }
1875     }
1876     else
1877     {
1878         COPY4(key->ip_l, sfaddr_get_ip6_ptr(dst));
1879         key->port_l = dport;
1880         COPY4(key->ip_h, sfaddr_get_ip6_ptr(src));
1881         key->port_h = sport;
1882 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1883         key->addressSpaceId_l = address_space_id_dst;
1884         key->addressSpaceId_h = address_space_id_src;
1885 #endif
1886     }
1887 # ifdef MPLS
1888     if (ScMplsOverlappingIp())
1889     {
1890         key->mplsLabel = mplsId;
1891     }
1892     else
1893     {
1894         key->mplsLabel = 0;
1895     }
1896 # else
1897     key->mplsLabel = 0;
1898 # endif
1899 
1900     key->protocol = proto;
1901 
1902     if (!ScVlanAgnostic())
1903         key->vlan_tag = vlan;
1904     else
1905         key->vlan_tag = 0;
1906 
1907     key->pad = 0;
1908 #if !defined(DAQ_CAPA_VRF) || defined(SFLINUX)
1909 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1910     if (!ScAddressSpaceAgnostic())
1911         key->addressSpaceId = addressSpaceId;
1912     else
1913         key->addressSpaceId = 0;
1914 #else
1915     key->addressSpaceId = 0;
1916 #endif
1917     key->addressSpaceIdPad1 = 0;
1918 #endif
1919 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
1920         key->carrierId = carrierId;
1921 #endif
1922     return 1;
1923 }
1924 
getSessionKey(Packet * p,SessionKey * key)1925 static int getSessionKey(Packet *p, SessionKey *key)
1926 {
1927     char proto = GET_IPH_PROTO(p);
1928     uint32_t mplsId = 0;
1929     uint16_t vlanId = 0;
1930     uint16_t sport = p->sp;
1931 # ifdef MPLS
1932     if (ScMplsOverlappingIp() && (p->mpls != NULL))
1933     {
1934         mplsId = p->mplsHdr.label;
1935     }
1936 #endif
1937 
1938     if (p->vh && !ScVlanAgnostic())
1939         vlanId = (uint16_t)VTH_VLAN(p->vh);
1940     if ((proto == IPPROTO_ICMP) || (proto == IPPROTO_ICMPV6))
1941     {
1942         /* ICMP */
1943         sport = p->icmph->type;
1944     }
1945 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
1946    uint32_t cid = GET_OUTER_IPH_PROTOID(p, pkth);
1947 
1948 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1949     uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
1950     uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
1951 
1952     return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1953                                        proto, vlanId, mplsId, sAsId, dAsId, cid, key);
1954 #else
1955     uint16_t addressSpaceId = 0;
1956 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1957     addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
1958 #endif
1959     return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1960                                        proto, vlanId, mplsId, addressSpaceId, cid, key);
1961 #endif
1962 #else /* No CarrierId support */
1963 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1964     uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
1965     uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
1966 
1967     return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1968                                        proto, vlanId, mplsId, sAsId, dAsId, key);
1969 #else
1970     uint16_t addressSpaceId = 0;
1971 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1972     addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
1973 #endif
1974     return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1975                                        proto, vlanId, mplsId, addressSpaceId, key);
1976 #endif
1977 #endif
1978 }
1979 
determinePacketDirection(Packet * p,uint16_t p_port,uint16_t scb_port,int is_sport)1980 static inline void determinePacketDirection( Packet *p, uint16_t p_port, uint16_t scb_port, int is_sport )
1981 {
1982     if ( is_sport )
1983         p->packet_flags |= ( p_port == scb_port ) ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
1984     else
1985         p->packet_flags |= ( p_port == scb_port ) ? PKT_FROM_SERVER : PKT_FROM_CLIENT;
1986 }
1987 
setPacketDirectionFlag(Packet * p,void * session)1988 static void setPacketDirectionFlag(Packet *p, void *session)
1989 {
1990     SessionControlBlock *scb = ( SessionControlBlock  *) session;
1991 
1992     if(IS_IP4(p))
1993     {
1994         if (sfip_fast_eq4(&p->ip4h->ip_addrs->ip_src, &scb->client_ip))
1995         {
1996             if (GET_IPH_PROTO(p) == IPPROTO_TCP)
1997                 determinePacketDirection(p, p->tcph->th_sport, scb->client_port, true);
1998             else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
1999                 determinePacketDirection(p, p->udph->uh_sport, scb->client_port, true);
2000             else
2001                 p->packet_flags |= PKT_FROM_CLIENT;
2002         }
2003         else if (sfip_fast_eq4(&p->ip4h->ip_addrs->ip_dst, &scb->client_ip))
2004         {
2005             if (GET_IPH_PROTO(p) == IPPROTO_TCP)
2006                 determinePacketDirection(p, p->tcph->th_dport, scb->client_port, false);
2007             else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
2008                 determinePacketDirection(p, p->udph->uh_dport, scb->client_port, false);
2009             else
2010                 p->packet_flags |= PKT_FROM_SERVER;
2011         }
2012     }
2013     else /* IS_IP6(p) */
2014     {
2015         if (sfip_fast_eq6(&p->ip6h->ip_addrs->ip_src, &scb->client_ip))
2016         {
2017             if (GET_IPH_PROTO(p) == IPPROTO_TCP)
2018                 determinePacketDirection(p, p->tcph->th_sport, scb->client_port, true);
2019             else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
2020                 determinePacketDirection(p, p->udph->uh_sport, scb->client_port, true);
2021             else
2022                 p->packet_flags |= PKT_FROM_CLIENT;
2023         }
2024         else if (sfip_fast_eq6(&p->ip6h->ip_addrs->ip_dst, &scb->client_ip))
2025         {
2026             if (GET_IPH_PROTO(p) == IPPROTO_TCP)
2027                 determinePacketDirection(p, p->tcph->th_dport, scb->client_port, false);
2028             else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
2029                 determinePacketDirection(p, p->udph->uh_dport, scb->client_port, false);
2030             else
2031                 p->packet_flags |= PKT_FROM_SERVER;
2032         }
2033     }
2034 }
2035 
getSessionControlBlock(SessionCache * sessionCache,Packet * p,SessionKey * key)2036 static void *getSessionControlBlock( SessionCache* sessionCache, Packet *p, SessionKey *key )
2037 {
2038     SessionControlBlock *scb = NULL;
2039     scb = ( SessionControlBlock *) checkSessionControlBlock ( sessionCache, p, key );
2040     updateSessionControlBlockTime ( scb, p );
2041     return scb;
2042 }
2043 
checkSessionControlBlock(void * sessionCache,Packet * p,SessionKey * key)2044 static void *checkSessionControlBlock( void *sessionCache, Packet *p, SessionKey *key )
2045 {
2046     // Retrieve the SCB without updating the last_data_seen time on the SCB
2047     SessionControlBlock *scb = NULL;
2048 
2049     if( getSessionKey( p, key ) )
2050     {
2051         scb = getSessionControlBlockFromKey( sessionCache, key );
2052     }
2053     return scb;
2054 }
2055 
updateSessionControlBlockTime(SessionControlBlock * scb,Packet * p)2056 static void updateSessionControlBlockTime(SessionControlBlock *scb, Packet *p)
2057 {
2058     if( scb != NULL )
2059     {
2060        if( scb->last_data_seen < p->pkth->ts.tv_sec )
2061           scb->last_data_seen = p->pkth->ts.tv_sec;
2062     }
2063 }
2064 
populateSessionKey(Packet * p,SessionKey * key)2065 static void populateSessionKey( Packet *p, SessionKey *key )
2066 {
2067 
2068     if (!key || !p)
2069         return;
2070 
2071 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2072     uint32_t cid = GET_OUTER_IPH_PROTOID(p, pkth);
2073 
2074 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
2075     uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
2076     uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
2077 
2078     initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2079                                  GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2080                                  p->mplsHdr.label, sAsId, dAsId, cid, key);
2081 #else
2082     uint16_t addressSpaceId = 0;
2083 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2084     addressSpaceId = DAQ_GetAddressSpaceID( p->pkth );
2085 #endif
2086 
2087     initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2088                                  GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2089                                  p->mplsHdr.label, addressSpaceId, cid, key);
2090 #endif
2091 #else /* No Carrierid support */
2092 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
2093     uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
2094     uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
2095 
2096     initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2097                                  GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2098                                  p->mplsHdr.label, sAsId, dAsId, key);
2099 #else
2100     uint16_t addressSpaceId = 0;
2101 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2102     addressSpaceId = DAQ_GetAddressSpaceID( p->pkth );
2103 #endif
2104 
2105     initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2106                                  GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2107                                  p->mplsHdr.label, addressSpaceId, key);
2108 #endif
2109 #endif
2110 }
2111 
getSessionControlBlockFromKey(SessionCache * session_cache,const SessionKey * key)2112 static void *getSessionControlBlockFromKey( SessionCache* session_cache, const SessionKey *key )
2113 {
2114     SessionControlBlock *scb = NULL;
2115     SFXHASH_NODE *hnode;
2116 
2117     if( !session_cache )
2118         return NULL;
2119 
2120     hnode = sfxhash_find_node( session_cache->hashTable, key );
2121 
2122     if( hnode && hnode->data )
2123     {
2124         /* This is a unique hnode, since the sfxhash finds the
2125          * same key before returning this node.
2126          */
2127         scb = ( SessionControlBlock * ) hnode->data;
2128     }
2129 
2130     return scb;
2131 }
2132 
freeSessionApplicationData(void * session)2133 static void freeSessionApplicationData(void *session)
2134 {
2135     SessionControlBlock *scb = ( SessionControlBlock  *) session;
2136 
2137     StreamAppData *tmpData, *appData = scb->appDataList;
2138     while( appData )
2139     {
2140         if( appData->freeFunc && appData->dataPointer )
2141             appData->freeFunc( appData->dataPointer );
2142 
2143         tmpData = appData->next;
2144         SnortPreprocFree(appData, sizeof(StreamAppData), PP_STREAM,
2145                     PP_MEM_CATEGORY_SESSION);
2146         appData = tmpData;
2147         scb->appDataList = appData;
2148     }
2149 }
2150 
removeSession(SessionCache * session_cache,SessionControlBlock * scb)2151 static int removeSession(SessionCache *session_cache, SessionControlBlock *scb )
2152 {
2153     SFXHASH_NODE *hnode;
2154 
2155     decrementPolicySessionRefCount( scb );
2156 
2157     mempool_free(&sessionFlowMempool, scb->flowdata);
2158     scb->flowdata = NULL;
2159 
2160     hnode = sfxhash_find_node(session_cache->hashTable, scb->key);
2161     if (!hnode)
2162         return SFXHASH_ERR;
2163     if (session_cache->nextTimeoutEvalNode == hnode)
2164         session_cache->nextTimeoutEvalNode = NULL;
2165 
2166     return sfxhash_free_node(session_cache->hashTable, hnode);
2167 }
2168 
deleteSessionByKey(void * session,char * delete_reason)2169 static int deleteSessionByKey(void *session, char *delete_reason)
2170 {
2171     SessionCache *session_cache;
2172     SessionControlBlock *scb = ( SessionControlBlock  *) session;
2173 
2174     assert( ( NULL != scb ) && ( NULL != scb->key ) );
2175 
2176     switch(scb->key->protocol)
2177     {
2178         case IPPROTO_TCP:
2179             session_cache = proto_session_caches[SESSION_PROTO_TCP];
2180             break;
2181         case IPPROTO_UDP:
2182             session_cache = proto_session_caches[SESSION_PROTO_UDP];
2183             break;
2184         case IPPROTO_ICMP:
2185             session_cache = proto_session_caches[SESSION_PROTO_ICMP];
2186             if (session_cache) break;
2187         default:
2188             session_cache = proto_session_caches[SESSION_PROTO_IP];
2189             break;
2190     }
2191 
2192     return deleteSession(session_cache, session, delete_reason, false);
2193 }
2194 
deleteSession(SessionCache * session_cache,void * session,char * delete_reason,bool close_sync)2195 static int deleteSession(SessionCache* session_cache, void *session, char *delete_reason, bool close_sync)
2196 {
2197     sfaddr_t client_ip;
2198     sfaddr_t server_ip;
2199     uint16_t client_port;
2200     uint16_t server_port;
2201     uint16_t lw_session_state;
2202     uint16_t lw_session_flags;
2203     int16_t app_proto_id;
2204     uint32_t prune_log_max;
2205     uint32_t old_mem_in_use;
2206     int ret;
2207     bool saved_pkt_trace = false;
2208 
2209     SessionControlBlock *scb = ( SessionControlBlock  *) session;
2210 
2211     assert( ( NULL != session_cache ) && ( NULL != scb ) );
2212 
2213     if(!close_sync && pkt_trace_enabled)
2214     {
2215         SavePktTrace();
2216         saved_pkt_trace = true;
2217     }
2218 
2219     if(!close_sync)
2220         pkt_trace_enabled = pktTracerDebugCheckSsn((void *)scb);
2221 
2222     if (pkt_trace_enabled)
2223         addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
2224                     "Session: deleting snort session, reason: %s\n",delete_reason ?delete_reason:"unknown"));
2225 
2226     /* Save the current mem in use before pruning */
2227     old_mem_in_use = session_mem_in_use;
2228 
2229     /* And save some info on that session */
2230     client_port = ntohs(scb->client_port);
2231     server_port = ntohs(scb->server_port);
2232     lw_session_state = scb->session_state;
2233     lw_session_flags = scb->ha_state.session_flags;
2234 #ifdef TARGET_BASED
2235     app_proto_id = scb->ha_state.application_protocol;
2236 #endif
2237 
2238     sfip_set_ip(&client_ip, &scb->client_ip);
2239     sfip_set_ip(&server_ip, &scb->server_ip);
2240 
2241 #ifdef MPLS
2242     if( scb->clientMplsHeader != NULL && scb->serverMplsHeader != NULL )
2243         freeMplsHeaders(scb);
2244 #endif
2245 
2246 #ifdef ENABLE_HA
2247     if ( !(session_cache->flags & SESSION_CACHE_FLAG_PURGING) )
2248         SessionHANotifyDeletion(scb);
2249 #endif
2250 
2251     /*
2252      * Call callback to cleanup the protocol (TCP/UDP/ICMP)
2253      * specific session details
2254      */
2255     if ( session_cache->cleanup_fcn )
2256         session_cache->cleanup_fcn(scb);
2257 
2258     freeSessionApplicationData(scb);
2259 
2260     /* Need to save this off since the global config might be from an
2261      * older session - because of a reload - and that config might
2262      * get freed after removing the session */
2263     prune_log_max = GetSessionPruneLogMax( );
2264 
2265     // if sessions is in the one-way list then remove it...
2266     if( scb->in_oneway_list )
2267         removeFromOneWaySessionList( session_cache, scb );
2268 
2269     ret = removeSession(session_cache, scb);
2270 
2271     /* If we're pruning and we clobbered some large amount, log a
2272      * message about that session. */
2273     if ( prune_log_max
2274             && ((old_mem_in_use - session_mem_in_use ) > prune_log_max) )
2275     {
2276       char *client_ip_str, *server_ip_str;
2277       client_ip_str = SnortStrdup(inet_ntoa(&client_ip));
2278       server_ip_str = SnortStrdup(inet_ntoa(&server_ip));
2279       LogMessage("S5: Pruned session from cache that was "
2280           "using %d bytes (%s). %s %d --> %s %d "
2281 #ifdef TARGET_BASED
2282           "(%d) "
2283 #endif
2284           ": LWstate 0x%x LWFlags 0x%x\n",
2285           old_mem_in_use - session_mem_in_use,
2286           delete_reason?delete_reason:"Unknown",
2287           client_ip_str, client_port,
2288           server_ip_str, server_port,
2289 #ifdef TARGET_BASED
2290           app_proto_id,
2291 #endif
2292           lw_session_state, lw_session_flags);
2293 	  free(client_ip_str);
2294 	  free(server_ip_str);
2295     }
2296 
2297     if (pkt_trace_enabled)
2298         addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
2299                     "Session: deleted snort session using %d bytes; "
2300 #ifdef TARGET_BASED
2301                     "protocol id:(%d) "
2302 #endif
2303                     ": LWstate 0x%x LWFlags 0x%x\n",
2304                     old_mem_in_use - session_mem_in_use,
2305 #ifdef TARGET_BASED
2306                     app_proto_id,
2307 #endif
2308                     lw_session_state, lw_session_flags));
2309 
2310     if(saved_pkt_trace)
2311     {
2312         pkt_trace_enabled = true;
2313         RestorePktTrace();
2314     }
2315     else if(!close_sync)
2316         pkt_trace_enabled = false;
2317 
2318     return ret;
2319 }
2320 
purgeSessionCache(SessionCache * session_cache)2321 static int purgeSessionCache(SessionCache* session_cache)
2322 {
2323     int retCount = 0;
2324     SessionControlBlock *idx;
2325     SFXHASH_NODE *hnode;
2326 
2327     if (!session_cache)
2328         return 0;
2329 
2330     session_cache->flags |= SESSION_CACHE_FLAG_PURGING;
2331 
2332     /* Remove all sessions from the hash table. */
2333     hnode = sfxhash_mru_node(session_cache->hashTable);
2334     while (hnode)
2335     {
2336         idx = (SessionControlBlock *)hnode->data;
2337         if (!idx)
2338         {
2339             sfxhash_free_node(session_cache->hashTable, hnode);
2340         }
2341         else
2342         {
2343             idx->ha_state.session_flags |= SSNFLAG_PRUNED;
2344             deleteSession(session_cache, idx, "purge whole cache", false);
2345         }
2346         hnode = sfxhash_mru_node(session_cache->hashTable);
2347         retCount++;
2348     }
2349 
2350     session_cache->flags &= ~SESSION_CACHE_FLAG_PURGING;
2351 
2352     return retCount;
2353 }
2354 
deleteSessionCache(uint32_t protocol)2355 static int deleteSessionCache( uint32_t protocol )
2356 {
2357     int retCount = 0;
2358     SessionCache *session_cache = NULL;
2359 
2360     if( protocol < SESSION_PROTO_MAX )
2361         session_cache = proto_session_caches[ protocol ];
2362 
2363     if( session_cache )
2364     {
2365         retCount = purgeSessionCache(session_cache);
2366 
2367         // release memory allocated for protocol specific session data
2368         mempool_destroy( session_cache->protocol_session_pool );
2369         free( session_cache->protocol_session_pool );
2370 
2371         sfxhash_delete( session_cache->hashTable );
2372         free( session_cache );
2373         proto_session_caches[ protocol ] = NULL;
2374     }
2375 
2376     return retCount;
2377 }
2378 
isSessionBlocked(SessionControlBlock * session)2379 static inline bool isSessionBlocked (SessionControlBlock* session)
2380 {
2381     SessionControlBlock *scb = ( SessionControlBlock  *) session;
2382 
2383     return ( scb->ha_state.session_flags & ( SSNFLAG_DROP_CLIENT | SSNFLAG_DROP_SERVER ) ) != 0;
2384 }
2385 
pruneOneWaySessions(SessionCache * session_cache)2386 static int pruneOneWaySessions( SessionCache *session_cache )
2387 {
2388     unsigned num_pruned = 0;
2389 
2390     while( session_cache->ows_list.num_sessions > session_cache->ows_list.prune_threshold )
2391     {
2392         SessionControlBlock *scb = session_cache->ows_list.head;
2393         if( scb != NULL )
2394         {
2395             removeFromOneWaySessionList( session_cache, scb );
2396             deleteSession(session_cache, scb, "oneway", false);
2397             if( ++num_pruned > session_cache->ows_list.prune_max )
2398                 break;
2399         }
2400         else
2401         {
2402             WarningMessage("%s(%d) One Way Session Count Non-zero but list  head is NULL\n",
2403                     file_name, file_line );
2404             break;
2405         }
2406     }
2407 
2408     session_cache->prunes += num_pruned;
2409     return num_pruned;
2410 }
2411 
prune_more_sessions(SessionCache * session_cache,uint32_t num_pruned,uint32_t prune_stop_threshold,int memCheck)2412 static bool prune_more_sessions( SessionCache *session_cache, uint32_t num_pruned,
2413         uint32_t prune_stop_threshold, int memCheck )
2414 {
2415     unsigned int session_count = sfxhash_count(session_cache->hashTable);
2416 
2417     if( session_count < 1 )
2418         return false;
2419 
2420     if( !memCheck )
2421         return ( ( session_count > prune_stop_threshold ) || ( num_pruned == 0 ) );
2422     else
2423         return session_mem_in_use > GetSessionMemCap();
2424 }
2425 
moveHashNodeToFront(SessionCache * session_cache)2426 static void moveHashNodeToFront( SessionCache *session_cache )
2427 {
2428     SFXHASH_NODE *lastNode;
2429 
2430     lastNode = sfxhash_lru_node(session_cache->hashTable);
2431     if(lastNode)
2432     	sfxhash_gmovetofront(session_cache->hashTable, lastNode);
2433 }
2434 static ThrottleInfo error_throttleInfo = {0,60,0};
2435 
pruneSessionCache(SessionCache * session_cache,uint32_t thetime,void * save_me_session,int memCheck)2436 static int pruneSessionCache( SessionCache* session_cache, uint32_t thetime, void *save_me_session, int memCheck )
2437 {
2438     SessionControlBlock *save_me = ( SessionControlBlock  * ) save_me_session;
2439     SessionControlBlock *scb;
2440     uint32_t pruned = 0;
2441 
2442     Active_Suspend();
2443 
2444     if( thetime != 0 )
2445     {
2446         /* Pruning, look for sessions that have time'd out */
2447         bool got_one;
2448         scb = ( SessionControlBlock * ) sfxhash_lru( session_cache->hashTable );
2449 
2450         if( scb == NULL )
2451         {
2452             Active_Resume();
2453             return 0;
2454         }
2455 
2456         do
2457         {
2458             got_one = false;
2459             if( scb == save_me )
2460             {
2461                 SFXHASH_NODE *lastNode = sfxhash_lru_node( session_cache->hashTable );
2462                 sfxhash_gmovetofront( session_cache->hashTable, lastNode );
2463                 lastNode = sfxhash_lru_node( session_cache->hashTable );
2464                 if( ( lastNode ) && ( lastNode->data != scb ) )
2465                 {
2466                     scb = ( SessionControlBlock * ) lastNode->data;
2467                     got_one = true;
2468                     continue;
2469                 }
2470                 else
2471                 {
2472                     session_cache->prunes += pruned;
2473                     Active_Resume();
2474                     return pruned;
2475                 }
2476             }
2477 
2478             if((scb->last_data_seen + session_cache->timeoutAggressive) < thetime)
2479             {
2480                 SessionControlBlock *savscb = scb;
2481 
2482                 if(sfxhash_count(session_cache->hashTable) > 1)
2483                 {
2484                     DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning stale session\n"););
2485                     savscb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
2486                     deleteSession(session_cache, savscb, "stale/timeout", false);
2487 
2488                     scb = (SessionControlBlock *) sfxhash_lru(session_cache->hashTable);
2489                     pruned++;
2490                     got_one = true;
2491                 }
2492                 else
2493                 {
2494                     savscb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
2495                     deleteSession(session_cache, savscb, "stale/timeout/last scb", false);
2496                     pruned++;
2497                     session_cache->prunes += pruned;
2498                     Active_Resume();
2499                     return pruned;
2500                 }
2501             }
2502             else
2503             {
2504                 session_cache->prunes += pruned;
2505                 Active_Resume();
2506                 return pruned;
2507             }
2508 
2509             if (pruned > session_cache->cleanup_sessions)
2510             {
2511                 /* Don't bother cleaning more than 'n' at a time */
2512                 break;
2513             }
2514         } while( ( scb != NULL ) && got_one );
2515 
2516         session_cache->prunes += pruned;
2517         Active_Resume();
2518         return pruned;
2519     }
2520     else
2521     {
2522         /* Free up to 'n' sessions at a time until we get under the memcap or free
2523          * enough sessions to be able to create new ones.
2524          */
2525         uint32_t prune_stop_threshold = session_cache->max_sessions - session_cache->cleanup_sessions;
2526         while( prune_more_sessions( session_cache, pruned, prune_stop_threshold, memCheck ) )
2527         {
2528             unsigned int blocks = 0;
2529             DEBUG_WRAP( DebugMessage(DEBUG_STREAM,
2530                         "S5: Pruning session cache by %d scbs for %s: %d/%d\n",
2531                         session_cache->cleanup_sessions,
2532                         memCheck ? "memcap" : "hash limit",
2533                         session_mem_in_use,
2534                         GetSessionMemCap() ););
2535 
2536             scb = (SessionControlBlock *) sfxhash_lru(session_cache->hashTable);
2537 
2538             if( scb == NULL )
2539                 break;
2540 
2541             if( scb == save_me )
2542             {
2543                 if(sfxhash_count(session_cache->hashTable) == 1)
2544                     break;
2545                 moveHashNodeToFront( session_cache );
2546                 continue;
2547             }
2548 
2549             if( memCheck )
2550             {
2551                 if ( isSessionBlocked( scb ) )
2552                 {
2553                     if( ++blocks >= sfxhash_count( session_cache->hashTable ) )
2554                         break;
2555 
2556                     moveHashNodeToFront( session_cache );
2557                     continue;
2558                 }
2559                 else
2560                 {
2561                     scb->ha_state.session_flags |= SSNFLAG_PRUNED;
2562                     deleteSession( session_cache, scb, "memcap/check", false );
2563                     pruned++;
2564                 }
2565             }
2566             else
2567             {
2568                 scb->ha_state.session_flags |= SSNFLAG_PRUNED;
2569                 deleteSession( session_cache, scb, "memcap/stale", false );
2570                 pruned++;
2571             }
2572 
2573             if ( pruned >= session_cache->cleanup_sessions )
2574                 break;
2575         }
2576     }
2577 
2578     if( memCheck && pruned )
2579     {
2580 	ErrorMessageThrottled(&error_throttleInfo,"S5: Pruned %d sessions from cache for memcap. %d scbs remain. memcap: %d/%d\n",
2581                     pruned, sfxhash_count( session_cache->hashTable ),
2582                     session_mem_in_use,
2583                     GetSessionMemCap() );
2584         DEBUG_WRAP( if( sfxhash_count(session_cache->hashTable) == 1 )
2585                     {
2586                         DebugMessage(DEBUG_STREAM, "S5: Pruned, one session remains\n");
2587                     } );
2588     }
2589     session_cache->prunes += pruned;
2590     Active_Resume();
2591     return pruned;
2592 }
2593 
freeMplsHeaders(SessionControlBlock * scb)2594 static void freeMplsHeaders(SessionControlBlock *scb)
2595 {
2596     if ( scb->clientMplsHeader->start != NULL )
2597     {
2598          SnortPreprocFree(scb->clientMplsHeader->start,
2599                           scb->clientMplsHeader->length, PP_STREAM,
2600                           PP_MEM_CATEGORY_SESSION);
2601          scb->clientMplsHeader->start = NULL;
2602     }
2603     SnortPreprocFree(scb->clientMplsHeader, sizeof(MPLS_Hdr), PP_STREAM,
2604                      PP_MEM_CATEGORY_SESSION);
2605     scb->clientMplsHeader = NULL;
2606     if (scb->serverMplsHeader->start != NULL )
2607     {
2608          SnortPreprocFree(scb->serverMplsHeader->start,
2609                      scb->serverMplsHeader->length, PP_STREAM,
2610                      PP_MEM_CATEGORY_SESSION);
2611          scb->serverMplsHeader->start = NULL;
2612     }
2613     SnortPreprocFree(scb->serverMplsHeader, sizeof(MPLS_Hdr),
2614                     PP_STREAM, 0);
2615     scb->serverMplsHeader = NULL;
2616 }
2617 
initMplsHeaders(SessionControlBlock * scb)2618 static void initMplsHeaders(SessionControlBlock *scb)
2619 {
2620     scb->clientMplsHeader = (MPLS_Hdr*)SnortPreprocAlloc(1, sizeof(MPLS_Hdr),
2621                                          PP_STREAM, PP_MEM_CATEGORY_CONFIG);
2622     scb->serverMplsHeader = (MPLS_Hdr*)SnortPreprocAlloc(1, sizeof(MPLS_Hdr),
2623                                          PP_STREAM, PP_MEM_CATEGORY_CONFIG);
2624 }
2625 
2626 
createSession(SessionCache * session_cache,Packet * p,const SessionKey * key)2627 static void *createSession(SessionCache* session_cache, Packet *p, const SessionKey *key )
2628 {
2629     SessionControlBlock *scb = NULL;
2630     SFXHASH_NODE *hnode;
2631     StreamFlowData *flowdata;
2632     time_t timestamp = p ? p->pkth->ts.tv_sec : packet_time();
2633 
2634     if( session_cache == NULL )
2635         return NULL;
2636 
2637     hnode = sfxhash_get_node(session_cache->hashTable, key);
2638     if (!hnode)
2639     {
2640         DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, clean One Way Sessions.\n"););
2641         if( pruneOneWaySessions( session_cache ) == 0 )
2642         {
2643             DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "No One Way Sessions, clean timedout sessions.\n"););
2644             if( pruneSessionCache(session_cache, timestamp, NULL, 0) == 0 )
2645             {
2646                 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "No timedout sessions, clean least recently used.\n"););
2647                 pruneSessionCache(session_cache, 0, NULL, 0);
2648             }
2649         }
2650 
2651         /* Should have some freed nodes now */
2652         hnode = sfxhash_get_node(session_cache->hashTable, key);
2653 #ifdef DEBUG_MSGS
2654         if (!hnode)
2655             LogMessage("%s(%d) Problem, no freed nodes\n", __FILE__, __LINE__);
2656 #endif
2657     }
2658 
2659     if (hnode && hnode->data)
2660     {
2661         scb = hnode->data;
2662 
2663         /* Zero everything out */
2664         memset(scb, 0, sizeof(SessionControlBlock));
2665 
2666         /* Save the session key for future use */
2667         scb->key = hnode->key;
2668         scb->session_state = STREAM_STATE_NONE;
2669         scb->session_established = false;
2670         scb->protocol = key->protocol;
2671         scb->last_data_seen = timestamp;
2672         scb->flowdata = mempool_alloc(&sessionFlowMempool);
2673         if( scb->flowdata )
2674         {
2675             flowdata = scb->flowdata->data;
2676             boInitStaticBITOP(&(flowdata->boFlowbits), getFlowbitSizeInBytes(), flowdata->flowb);
2677         }
2678 
2679         scb->stream_config_stale = true;
2680         scb->stream_config = NULL;
2681         scb->proto_policy = NULL;
2682         scb->napPolicyId = SF_POLICY_UNBOUND;
2683         scb->ipsPolicyId = SF_POLICY_UNBOUND;
2684         scb->session_config = session_configuration;
2685 
2686         scb->port_guess = true;
2687 
2688 #ifdef MPLS
2689    if( p != NULL )
2690    {
2691         uint8_t layerIndex;
2692         for(layerIndex=0; layerIndex < p->next_layer; layerIndex++)
2693         {
2694              if( p->layers[layerIndex].proto == PROTO_MPLS && p->layers[layerIndex].start != NULL )
2695              {
2696                     initMplsHeaders(scb);
2697                     break;
2698              }
2699         }
2700    }
2701 #endif
2702 
2703 #ifdef ENABLE_HA
2704         if (session_configuration->enable_ha)
2705         {
2706             scb->ha_flags |= HA_FLAG_NEW;
2707             /* Calculate the threshold time for the first HA update message. */
2708             packet_gettimeofday(&scb->ha_next_update);
2709             if (session_configuration->ha_config)
2710             {
2711                 scb->ha_next_update.tv_usec += session_configuration->ha_config->min_session_lifetime.tv_usec;
2712                 if (scb->ha_next_update.tv_usec > 1000000)
2713                 {
2714                     scb->ha_next_update.tv_usec -= 1000000;
2715                     scb->ha_next_update.tv_sec++;
2716                 }
2717                 scb->ha_next_update.tv_sec += session_configuration->ha_config->min_session_lifetime.tv_sec;
2718             }
2719 
2720             memset( &scb->ha_state, '\0', sizeof( StreamHAState ) );
2721             scb->cached_ha_state = scb->ha_state;
2722             scb->new_session = true;
2723         }
2724 #endif
2725 
2726         // all sessions are one-way when created so add to oneway session list...
2727         insertIntoOneWaySessionList( session_cache, scb );
2728 
2729         if (pkt_trace_enabled)
2730             addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
2731                 "Session: new snort session\n"));
2732     }
2733 
2734     return scb;
2735 }
2736 
isSessionVerified(void * ssn)2737 static bool isSessionVerified( void *ssn )
2738 {
2739     if ( ssn != NULL )
2740         return ( ( SessionControlBlock * ) ssn )->session_established;
2741     else
2742         return false;
2743 }
2744 
removeSessionFromProtoOneWayList(uint32_t proto,void * scb)2745 static void removeSessionFromProtoOneWayList( uint32_t proto, void *scb )
2746 {
2747     if( proto < SESSION_PROTO_MAX )
2748     {
2749         removeFromOneWaySessionList( proto_session_caches[ proto ], ( SessionControlBlock * ) scb );
2750     }
2751     else
2752     {
2753         WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, proto);
2754     }
2755 }
2756 
cleanProtocolSessionsPool(uint32_t protocol)2757 static void cleanProtocolSessionsPool( uint32_t protocol )
2758 {
2759     if( protocol < SESSION_PROTO_MAX )
2760     {
2761         if( proto_session_caches[protocol] )
2762             mempool_clean( proto_session_caches[protocol]->protocol_session_pool );
2763     }
2764     else
2765     {
2766         WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
2767     }
2768 }
2769 
freeProtocolSessionsPool(uint32_t protocol,void * scb)2770 static void freeProtocolSessionsPool( uint32_t protocol, void *scb )
2771 {
2772     if( protocol < SESSION_PROTO_MAX )
2773     {
2774         if( proto_session_caches[protocol] )
2775             mempool_free( proto_session_caches[protocol]->protocol_session_pool,
2776                     ( ( SessionControlBlock * ) scb )->proto_specific_data );
2777     }
2778     else
2779     {
2780         WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
2781     }
2782 }
2783 
allocateProtocolSession(uint32_t protocol)2784 static void *allocateProtocolSession( uint32_t protocol )
2785 {
2786     if( protocol < SESSION_PROTO_MAX )
2787     {
2788         if( proto_session_caches[protocol] )
2789             return mempool_force_alloc( proto_session_caches[protocol]->protocol_session_pool );
2790     }
2791     else
2792     {
2793         WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
2794     }
2795 
2796     return NULL;
2797 }
2798 
2799 
HashFunc(SFHASHFCN * p,unsigned char * d,int n)2800 static uint32_t HashFunc(SFHASHFCN *p, unsigned char *d, int n)
2801 {
2802     uint32_t a,b,c;
2803     uint32_t offset = 0;
2804 #ifdef MPLS
2805     uint32_t tmp = 0;
2806 #endif
2807 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2808     uint32_t tmp2 = 0;
2809 #endif
2810 
2811     a = *(uint32_t*)d;         /* IPv6 lo[0] */
2812     b = *(uint32_t*)(d+4);     /* IPv6 lo[1] */
2813     c = *(uint32_t*)(d+8);     /* IPv6 lo[2] */
2814 
2815     mix(a,b,c);
2816 
2817     a += *(uint32_t*)(d+12);   /* IPv6 lo[3] */
2818     b += *(uint32_t*)(d+16);   /* IPv6 hi[0] */
2819     c += *(uint32_t*)(d+20);   /* IPv6 hi[1] */
2820 
2821     mix(a,b,c);
2822 
2823     a += *(uint32_t*)(d+24);   /* IPv6 hi[2] */
2824     b += *(uint32_t*)(d+28);   /* IPv6 hi[3] */
2825     c += *(uint32_t*)(d+32);   /* port lo & port hi */
2826 
2827     mix(a,b,c);
2828 
2829     offset=36;
2830     a += *(uint32_t*)(d+offset);   /* vlan, protocol, & pad */
2831 #ifdef MPLS
2832     tmp = *(uint32_t *)(d+offset+4);
2833     if( tmp )
2834     {
2835         b += tmp;   /* mpls label */
2836     }
2837     offset += 8;    /* skip past vlan/proto/ipver & mpls label */
2838 #else
2839     offset += 4;    /* skip past vlan/proto/ipver */
2840 #endif
2841 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2842     tmp2 = *(uint32_t*)(d+offset); /* after offset that has been moved */
2843     c += tmp2; /* address space id and 16bits of zero'd pad */
2844 #endif
2845 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2846     mix(a,b,c);
2847     a += *(uint32_t*)(d+offset+4);
2848 #endif
2849 
2850     final(a,b,c);
2851 
2852     return c;
2853 }
2854 
HashKeyCmp(const void * s1,const void * s2,size_t n)2855 static int HashKeyCmp(const void *s1, const void *s2, size_t n)
2856 {
2857 #ifndef SPARCV9 /* ie, everything else, use 64bit comparisons */
2858     uint64_t *a,*b;
2859 
2860     a = (uint64_t*)s1;
2861     b = (uint64_t*)s2;
2862     if(*a - *b) return 1;       /* Compares IPv4 lo/hi */
2863     /* Compares IPv6 low[0,1] */
2864 
2865     a++;
2866     b++;
2867     if(*a - *b) return 1;       /* Compares port lo/hi, vlan, protocol, pad */
2868     /* Compares IPv6 low[2,3] */
2869 
2870     a++;
2871     b++;
2872     if(*a - *b) return 1;       /* Compares IPv6 hi[0,1] */
2873 
2874     a++;
2875     b++;
2876     if(*a - *b) return 1;       /* Compares IPv6 hi[2,3] */
2877 
2878     a++;
2879     b++;
2880     if(*a - *b) return 1;       /* Compares port lo/hi, vlan, protocol, pad */
2881 
2882 #ifdef MPLS
2883     a++;
2884     b++;
2885 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2886     if (*a - *b) return 1;      /* Compares MPLS label, AddressSpace ID and 16bit pad */
2887 #else
2888     {
2889         uint32_t *x, *y;
2890         x = (uint32_t *)a;
2891         y = (uint32_t *)b;
2892         //x++;
2893         //y++;
2894         if (*x - *y) return 1;  /* Compares mpls label, no pad */
2895     }
2896 #endif
2897 #else
2898 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2899     a++;
2900     b++;
2901     {
2902         uint16_t *x, *y;
2903         x = (uint16_t *)a;
2904         y = (uint16_t *)b;
2905         //x++;
2906         //y++;
2907         if (*x - *y) return 1;  /* Compares addressSpaceID, no pad */
2908     }
2909 #endif
2910 #endif
2911 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2912    a++;
2913    b++;
2914    {
2915         uint32_t *x, *y;
2916         x = (uint32_t *)a;
2917         y = (uint32_t *)b;
2918         if (*x - *y) return 1; /* Compares carrierID */
2919    }
2920 #endif
2921 
2922 #else /* SPARCV9 */
2923     uint32_t *a,*b;
2924 
2925     a = (uint32_t*)s1;
2926     b = (uint32_t*)s2;
2927     if ((*a - *b) || (*(a+1) - *(b+1))) return 1;       /* Compares IPv4 lo/hi */
2928     /* Compares IPv6 low[0,1] */
2929 
2930     a+=2;
2931     b+=2;
2932     if ((*a - *b) || (*(a+1) - *(b+1))) return 1;       /* Compares port lo/hi, vlan, protocol, pad */
2933     /* Compares IPv6 low[2,3] */
2934 
2935     a+=2;
2936     b+=2;
2937     if ((*a - *b) || (*(a+1) - *(b+1))) return 1;       /* Compares IPv6 hi[0,1] */
2938 
2939     a+=2;
2940     b+=2;
2941     if ((*a - *b) || (*(a+1) - *(b+1))) return 1;       /* Compares IPv6 hi[2,3] */
2942 
2943     a+=2;
2944     b+=2;
2945     if ((*a - *b) || (*(a+1) - *(b+1))) return 1;       /* Compares port lo/hi, vlan, protocol, pad */
2946 
2947 #ifdef MPLS
2948     a+=2;
2949     b+=2;
2950     {
2951         uint32_t *x, *y;
2952         x = (uint32_t *)a;
2953         y = (uint32_t *)b;
2954         //x++;
2955         //y++;
2956         if (*x - *y) return 1;  /* Compares mpls label */
2957     }
2958 #endif
2959 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2960 #ifdef MPLS
2961     a++;
2962     b++;
2963 #else
2964     a+=2;
2965     b+=2;
2966 #endif
2967     {
2968         uint16_t *x, *y;
2969         x = (uint16_t *)a;
2970         y = (uint16_t *)b;
2971         //x++;
2972         //y++;
2973         if (*x - *y) return 1;  /* Compares addressSpaceID, no pad */
2974     }
2975 #endif
2976 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2977    a++;
2978    b++;
2979    {
2980         uint32_t *x, *y;
2981         x = (uint32_t *)a;
2982         y = (uint32_t *)b;
2983         if (*x - *y) return 1; /* Compares carrierID */
2984    }
2985 #endif
2986 #endif /* SPARCV9 */
2987 
2988     return 0;
2989 }
2990 
initSessionCache(uint32_t session_type,uint32_t protocol_scb_size,SessionCleanup cleanup_fcn)2991 static SessionCache* initSessionCache(uint32_t session_type, uint32_t protocol_scb_size, SessionCleanup cleanup_fcn)
2992 {
2993     int hashTableSize;
2994     SessionCache *sessionCache = NULL;
2995     uint32_t max_sessions = 0, session_timeout_min = 0, session_timeout_max = 0;
2996     uint32_t cleanup_sessions = 5;
2997 
2998     switch ( session_type )
2999     {
3000         case SESSION_PROTO_TCP:
3001             if( session_configuration->track_tcp_sessions == STREAM_TRACK_YES )
3002             {
3003                 max_sessions = session_configuration->max_tcp_sessions;
3004                 if (session_configuration->memcap > (max_sessions * protocol_scb_size))
3005                     session_configuration->memcap = session_configuration->memcap
3006                         - (max_sessions * protocol_scb_size);
3007                 session_timeout_min = session_configuration->tcp_cache_pruning_timeout;
3008                 session_timeout_max = session_configuration->tcp_cache_nominal_timeout;
3009             }
3010             break;
3011 
3012         case SESSION_PROTO_UDP:
3013             if( session_configuration->track_udp_sessions == STREAM_TRACK_YES )
3014             {
3015                 max_sessions = session_configuration->max_udp_sessions;
3016                 session_timeout_min = session_configuration->udp_cache_pruning_timeout;
3017                 session_timeout_max = session_configuration->udp_cache_nominal_timeout;
3018             }
3019             break;
3020 
3021         case SESSION_PROTO_ICMP:
3022             if( session_configuration->track_icmp_sessions == STREAM_TRACK_YES )
3023             {
3024                 max_sessions = session_configuration->max_icmp_sessions;
3025                 session_timeout_min = 30;
3026                 session_timeout_max = 3 * session_timeout_min;
3027             }
3028             break;
3029 
3030         case SESSION_PROTO_IP:
3031             if( session_configuration->track_ip_sessions == STREAM_TRACK_YES )
3032             {
3033                 max_sessions = session_configuration->max_ip_sessions;
3034                 session_timeout_min = 30;
3035                 session_timeout_max = 3 * session_timeout_min;
3036             }
3037             break;
3038 
3039         default:
3040             WarningMessage("%s(%d) Invalid session protocol type: %d", file_name, file_line, session_type);
3041             return NULL;
3042             break;
3043     }
3044 
3045     // only create a case for session controls for this protocol if tracking is enabled
3046     if( max_sessions > 0 )
3047     {
3048         // set hash table size to max sessions value...adjust up to avoid collisions????
3049         hashTableSize = max_sessions;
3050 
3051         sessionCache = SnortPreprocAlloc( 1, sizeof( SessionCache ), PP_STREAM,
3052                               PP_MEM_CATEGORY_CONFIG );
3053         if( sessionCache )
3054         {
3055             sessionCache->timeoutAggressive = session_timeout_min;
3056             sessionCache->timeoutNominal = session_timeout_max;
3057             sessionCache->max_sessions = max_sessions;
3058             if( cleanup_sessions < ( 2 * max_sessions ) )
3059                 sessionCache->cleanup_sessions = cleanup_sessions;
3060             else
3061                 sessionCache->cleanup_sessions = ( max_sessions / 2 );
3062             if( sessionCache->cleanup_sessions == 0 )
3063                 sessionCache->cleanup_sessions = 1;
3064 
3065             sessionCache->cleanup_fcn = cleanup_fcn;
3066 
3067             // init one way sessions list control block...
3068             sessionCache->ows_list.head = NULL;
3069             sessionCache->ows_list.tail = NULL;
3070             sessionCache->ows_list.num_sessions = 0;
3071             // tune these values for managing pruning of one-way sessions
3072             sessionCache->ows_list.prune_threshold = max_sessions * 0.05;
3073             if( sessionCache->ows_list.prune_threshold == 0 )
3074                 sessionCache->ows_list.prune_threshold = 10;
3075             sessionCache->ows_list.prune_max = sessionCache->ows_list.prune_threshold * 0.25;
3076 
3077             /* Okay, now create the table */
3078             sessionCache->hashTable = sfxhash_new( hashTableSize, sizeof(SessionKey), sizeof(SessionControlBlock),
3079                     //maxSessionMem + tableMem, 0, NULL, NULL, 1);
3080                 0, 0, NULL, NULL, 1 );
3081 
3082             sfxhash_set_max_nodes( sessionCache->hashTable, max_sessions );
3083             sfxhash_set_keyops( sessionCache->hashTable, HashFunc, HashKeyCmp );
3084 
3085             // now alloc and initial memory for protocol specific session blocks
3086             if( protocol_scb_size > 0 )
3087             {
3088                 sessionCache->protocol_session_pool = SnortAlloc(sizeof(MemPool));
3089                 if( mempool_init( sessionCache->protocol_session_pool, max_sessions, protocol_scb_size ) != 0 )
3090                 {
3091                     FatalError( "%s(%d) Could not initialize protocol session memory pool.\n",
3092                             __FILE__, __LINE__ );
3093                 }
3094             }
3095         }
3096         else
3097         {
3098             FatalError( "%s(%d) Unable to create a stream session cache for protocol type: %d.\n",
3099                     file_name, file_line, session_type);
3100         }
3101     }
3102     else
3103     {
3104         WarningMessage("%s(%d) Protocol tracking disabled for protocol type: %d\n",
3105                 file_name, file_line, session_type);
3106     }
3107 
3108     proto_session_caches[ session_type ] = sessionCache;
3109     return sessionCache;
3110 }
3111 
printSessionCache(SessionCache * sessionCache)3112 static void printSessionCache(SessionCache* sessionCache)
3113 {
3114     DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "%lu sessions active\n",
3115                 sfxhash_count( sessionCache->hashTable ) ););
3116 }
3117 
checkCacheFlowTimeout(uint32_t flowCount,time_t cur_time,SessionCache * cache)3118 static void checkCacheFlowTimeout(uint32_t flowCount, time_t cur_time, SessionCache *cache)
3119 {
3120     uint32_t flowRetiredCount = 0, flowExaminedCount = 0;
3121     SessionControlBlock *scb;
3122     SFXHASH_NODE *hnode, *hnode_prev;
3123 
3124     if( !cache )
3125         return;
3126 
3127     hnode_prev = cache->nextTimeoutEvalNode;
3128     while( flowRetiredCount < flowCount && flowExaminedCount < ( 2 * flowCount ) )
3129     {
3130         if( !( hnode = hnode_prev ) && !( hnode = sfxhash_lru_node( cache->hashTable ) ) )
3131             break;
3132 
3133         scb = ( SessionControlBlock * ) hnode->data;
3134         if( ( time_t ) ( scb->last_data_seen + cache->timeoutNominal ) > cur_time )
3135         {
3136             uint64_t time_jiffies;
3137             /*  Give extra 1 second delay*/
3138             time_jiffies = ((uint64_t)cur_time - 1) * TCP_HZ;
3139 
3140             if( !( ( scb->expire_time != 0 )  && ( cur_time != 0 ) && ( scb->expire_time <= time_jiffies ) ) )
3141                 break;
3142         }
3143 
3144         hnode_prev = hnode->gprev;
3145         flowExaminedCount++;
3146 
3147 #ifdef ENABLE_HA
3148         if( scb->ha_flags & HA_FLAG_STANDBY )
3149             continue;
3150 #endif
3151 
3152         DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "retiring stale session\n"););
3153         scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
3154         deleteSession(cache, scb, "stale/timeout", false);
3155         flowRetiredCount++;
3156     }
3157 
3158     cache->nextTimeoutEvalNode = hnode_prev;
3159 }
3160 
3161 /*get next flow from session cache. */
checkSessionTimeout(uint32_t flowCount,time_t cur_time)3162 static void checkSessionTimeout(uint32_t flowCount, time_t cur_time)
3163 {
3164     Active_Suspend( );
3165     checkCacheFlowTimeout(flowCount, cur_time, proto_session_caches[SESSION_PROTO_TCP]);
3166     checkCacheFlowTimeout(flowCount, cur_time, proto_session_caches[SESSION_PROTO_UDP]);
3167     checkCacheFlowTimeout(flowCount, cur_time, proto_session_caches[SESSION_PROTO_IP]);
3168     //icmp_lws_cache does not need cleaning
3169     Active_Resume( );
3170 }
3171 
isProtocolTrackingEnabled(IpProto proto)3172 static int isProtocolTrackingEnabled( IpProto proto )
3173 {
3174     int tracking_enabled = false;
3175 
3176     switch ( proto )
3177     {
3178         case SESSION_PROTO_TCP:
3179             tracking_enabled = session_configuration->track_tcp_sessions;
3180             break;
3181 
3182         case SESSION_PROTO_UDP:
3183             tracking_enabled = session_configuration->track_udp_sessions;
3184             break;
3185 
3186         case SESSION_PROTO_ICMP:
3187             tracking_enabled = session_configuration->track_icmp_sessions;
3188             break;
3189 
3190         case SESSION_PROTO_IP:
3191             tracking_enabled = session_configuration->track_ip_sessions;
3192             break;
3193 
3194         default:
3195             WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, proto);
3196             break;
3197     }
3198 
3199     return ( tracking_enabled );
3200 }
3201 
setApplicationData(void * scbptr,uint32_t protocol,void * data,StreamAppDataFree free_func)3202 static int setApplicationData( void *scbptr, uint32_t protocol, void *data, StreamAppDataFree free_func )
3203 {
3204     SessionControlBlock *scb;
3205     StreamAppData *appData = NULL;
3206     if (scbptr)
3207     {
3208         scb = ( SessionControlBlock * ) scbptr;
3209         appData = scb->appDataList;
3210         while (appData)
3211         {
3212             if (appData->protocol == protocol)
3213             {
3214                 /* If changing the pointer to the data, free old one */
3215                 if ((appData->freeFunc) && (appData->dataPointer != data))
3216                 {
3217                     if ( appData->dataPointer )
3218                         appData->freeFunc(appData->dataPointer);
3219                 }
3220                 else
3221                 {
3222                     /* Same pointer, same protocol.  Go away */
3223                     break;
3224                 }
3225 
3226                 appData->dataPointer = NULL;
3227                 break;
3228             }
3229 
3230             appData = appData->next;
3231         }
3232 
3233         /* If there isn't one for this protocol, allocate */
3234         if (!appData)
3235         {
3236             appData = SnortPreprocAlloc(1, sizeof(StreamAppData), PP_STREAM,
3237                               PP_MEM_CATEGORY_SESSION);
3238 
3239             /* And add it to the list */
3240             if (scb->appDataList)
3241             {
3242                 scb->appDataList->prev = appData;
3243             }
3244             appData->next = scb->appDataList;
3245             scb->appDataList = appData;
3246         }
3247 
3248         /* This will reset free_func if it already exists */
3249         appData->protocol = protocol;
3250         appData->freeFunc = free_func;
3251         appData->dataPointer = data;
3252 
3253         return 0;
3254     }
3255     return -1;
3256 }
3257 
getApplicationData(void * scbptr,uint32_t protocol)3258 static void *getApplicationData( void *scbptr, uint32_t protocol )
3259 {
3260     SessionControlBlock *scb;
3261     StreamAppData *appData = NULL;
3262     void *data = NULL;
3263     if (scbptr)
3264     {
3265         scb = ( SessionControlBlock* ) scbptr;
3266         appData = scb->appDataList;
3267         while (appData)
3268         {
3269             if (appData->protocol == protocol)
3270             {
3271                 data = appData->dataPointer;
3272                 break;
3273             }
3274             appData = appData->next;
3275         }
3276     }
3277     return data;
3278 }
3279 
getSessionHandle(const SessionKey * key)3280 static void * getSessionHandle(const SessionKey *key)
3281 {
3282     SessionControlBlock *scb;
3283 
3284     switch(key->protocol)
3285     {
3286         case IPPROTO_TCP:
3287             scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_TCP], key);
3288             break;
3289         case IPPROTO_UDP:
3290             scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_UDP], key);
3291             break;
3292         case IPPROTO_ICMP:
3293             scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_ICMP], key);
3294             if (scb) break;
3295             /* fall through */
3296         default:
3297             scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_IP], key);
3298             break;
3299     }
3300 
3301     return (void *)scb;
3302 }
3303 
getSessionHandleFromIpPort(sfaddr_t * srcIP,uint16_t srcPort,sfaddr_t * dstIP,uint16_t dstPort,char ip_protocol,uint16_t vlan,uint32_t mplsId,uint16_t address_space_id_src,uint16_t address_space_id_dst,uint32_t carrierId)3304 static void *getSessionHandleFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
3305                                          sfaddr_t* dstIP, uint16_t dstPort,
3306                                          char ip_protocol, uint16_t vlan,
3307                                          uint32_t mplsId,
3308 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3309                                          uint16_t address_space_id_src,
3310                                          uint16_t address_space_id_dst
3311 #else
3312                                          uint16_t addressSpaceId
3313 #endif
3314 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3315                                          , uint32_t carrierId
3316 #endif
3317                                         )
3318 {
3319     SessionKey key;
3320 
3321 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3322 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3323     initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3324                                 vlan, mplsId, address_space_id_src,
3325                                 address_space_id_dst, carrierId, &key);
3326 #else
3327     initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3328                                 vlan, mplsId, addressSpaceId, carrierId, &key);
3329 #endif
3330 #else /* No carrier id support */
3331 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3332     initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3333                                 vlan, mplsId, address_space_id_src,
3334                                 address_space_id_dst, &key);
3335 #else
3336     initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3337                                 vlan, mplsId, addressSpaceId, &key);
3338 #endif
3339 #endif
3340 
3341     return (void*)getSessionHandle(&key);
3342 }
3343 
getKeyFromSession(const void * scbptr)3344 static const StreamSessionKey *getKeyFromSession( const void *scbptr )
3345 {
3346     return ( ( SessionControlBlock * ) scbptr)->key;
3347 }
3348 
getSessionKeyFromPacket(Packet * p)3349 static StreamSessionKey *getSessionKeyFromPacket( Packet *p )
3350 {
3351     SessionKey *key = SnortPreprocAlloc(1, sizeof(*key), PP_STREAM,
3352                           PP_MEM_CATEGORY_SESSION);
3353 
3354     if (!key)
3355         return NULL;
3356 
3357 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3358     uint32_t cid = GET_OUTER_IPH_PROTOID(p, pkth);
3359 
3360 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3361     uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
3362     uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
3363 
3364     initSessionKeyFromPktHeader(GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp,
3365                                 GET_IPH_PROTO(p), p->vh ? VTH_VLAN(p->vh) : 0,
3366                                 p->mplsHdr.label, sAsId, dAsId, cid, key);
3367 #else
3368     uint16_t addressSpaceId = 0;
3369 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
3370     addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
3371 #endif
3372 
3373     initSessionKeyFromPktHeader( GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp, GET_IPH_PROTO(p),
3374                                  p->vh ? VTH_VLAN(p->vh) : 0,
3375                                  p->mplsHdr.label, addressSpaceId, cid, key);
3376 #endif
3377 #else /* No carrier id support */
3378 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3379     uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
3380     uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
3381 
3382     initSessionKeyFromPktHeader(GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp,
3383                                 GET_IPH_PROTO(p), p->vh ? VTH_VLAN(p->vh) : 0,
3384                                 p->mplsHdr.label, sAsId, dAsId, key);
3385 #else
3386     uint16_t addressSpaceId = 0;
3387 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
3388     addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
3389 #endif
3390 
3391     initSessionKeyFromPktHeader( GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp, GET_IPH_PROTO(p),
3392                                  p->vh ? VTH_VLAN(p->vh) : 0,
3393                                  p->mplsHdr.label, addressSpaceId, key);
3394 #endif
3395 #endif
3396     return key;
3397 }
3398 
getApplicationDataFromSessionKey(const StreamSessionKey * key,uint32_t protocol)3399 static void * getApplicationDataFromSessionKey(const StreamSessionKey *key, uint32_t protocol)
3400 {
3401     SessionControlBlock *scb = getSessionHandle(key);
3402     return getApplicationData(scb, protocol);
3403 }
3404 
getApplicationDataFromIpPort(sfaddr_t * srcIP,uint16_t srcPort,sfaddr_t * dstIP,uint16_t dstPort,uint16_t address_space_id_src,uint16_t address_space_id_dst,uint32_t carrierId,char ip_protocol,uint16_t vlan,uint32_t mplsId,uint32_t protocol)3405 static void *getApplicationDataFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
3406                                            sfaddr_t* dstIP, uint16_t dstPort,
3407 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3408                                            uint16_t address_space_id_src,
3409                                            uint16_t address_space_id_dst,
3410 #else
3411                                            uint16_t addressSpaceID,
3412 #endif
3413 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3414                                            uint32_t carrierId,
3415 #endif
3416                                            char ip_protocol, uint16_t vlan,
3417                                            uint32_t mplsId, uint32_t protocol
3418                                          )
3419 {
3420     SessionControlBlock *scb;
3421 
3422 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3423 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3424     scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort,
3425                                                              dstIP, dstPort,
3426                                                              ip_protocol, vlan,
3427                                                              mplsId, carrierId, address_space_id_src,
3428                                                              address_space_id_dst);
3429 #else
3430     scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort, dstIP,
3431                                                              dstPort, ip_protocol, vlan,
3432                                                              mplsId, carrierId, addressSpaceID);
3433 #endif
3434 #else /* No carrier id support */
3435 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3436     scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort,
3437                                                              dstIP, dstPort,
3438                                                              ip_protocol, vlan,
3439                                                              mplsId, address_space_id_src, address_space_id_dst);
3440 #else
3441     scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort, dstIP,
3442                                                              dstPort, ip_protocol, vlan,
3443                                                              mplsId, addressSpaceID);
3444 #endif
3445 #endif
3446 
3447     return getApplicationData(scb, protocol);
3448 }
3449 
deleteSessionIfClosed(Packet * p)3450 static void deleteSessionIfClosed( Packet* p )
3451 {
3452     SessionControlBlock* scb;
3453 
3454     if (!p || !p->ssnptr)
3455         return;
3456 
3457     scb = ( SessionControlBlock * ) p->ssnptr;
3458     if( !scb->session_established )
3459         return;
3460 
3461     if (scb->session_state & STREAM_STATE_CLOSED)
3462     {
3463         if (scb->is_session_deletion_delayed) {
3464             setSessionExpirationTime( p, scb, STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED);
3465             return;
3466         }
3467         switch (scb->protocol)
3468         {
3469             case IPPROTO_TCP:
3470                 deleteSession(proto_session_caches[SESSION_PROTO_TCP], scb, "closed normally", true);
3471                 p->ssnptr = NULL;
3472                 break;
3473             case IPPROTO_UDP:
3474                 deleteSession(proto_session_caches[SESSION_PROTO_UDP], scb, "closed normally", true);
3475                 p->ssnptr = NULL;
3476                 break;
3477             case IPPROTO_ICMP: /* matching how sessionPacketProcessor() stores ICMP sessions */
3478                 if ( SessionTrackingEnabled( session_configuration, SESSION_PROTO_ICMP ) )
3479                 {
3480                     deleteSession(proto_session_caches[SESSION_PROTO_ICMP], scb, "closed normally", true);
3481                     p->ssnptr = NULL;
3482                     break;
3483                 }
3484                 // fall thru, not tracking ICMP, treat as IP packet...
3485             case IPPROTO_IP:
3486             default: /* matching how sessionPacketProcessor() stores default sessions */
3487                 deleteSession(proto_session_caches[SESSION_PROTO_IP], scb, "closed normally", true);
3488                 p->ssnptr = NULL;
3489                 break;
3490         }
3491     }
3492 }
3493 
setSessionExpirationTime(Packet * p,void * scb,uint32_t timeout)3494 static void setSessionExpirationTime(Packet *p, void *scb, uint32_t timeout)
3495 {
3496     ( ( SessionControlBlock * ) scb)->expire_time = CalcJiffies(p) + (timeout * TCP_HZ);
3497     return;
3498 }
3499 
getSessionExpirationTime(Packet * p,void * scb)3500 static int getSessionExpirationTime(Packet *p, void *scb)
3501 {
3502     if ( ( ( SessionControlBlock * ) scb)->expire_time == 0 ) return 0;
3503     return ( CalcJiffies(p) > ( ( SessionControlBlock * ) scb)->expire_time );
3504 }
3505 
3506 #
setSessionFlags(void * scbptr,uint32_t flags)3507 static uint32_t setSessionFlags( void *scbptr, uint32_t flags )
3508 {
3509     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3510     if( scb)
3511     {
3512         if( ( scb->ha_state.session_flags & flags ) != flags )
3513         {
3514 #ifdef ENABLE_HA
3515             scb->ha_flags |= HA_FLAG_MODIFIED;
3516             if((scb->ha_state.session_flags & HA_CRITICAL_SESSION_FLAGS) != (flags & HA_CRITICAL_SESSION_FLAGS))
3517                 scb->ha_flags |= HA_FLAG_CRITICAL_CHANGE;
3518 
3519             if( scb->protocol == IPPROTO_TCP
3520                     &&
3521                     ( scb->ha_state.session_flags & HA_TCP_MAJOR_SESSION_FLAGS )
3522                     != ( flags & HA_TCP_MAJOR_SESSION_FLAGS ) )
3523                 scb->ha_flags |= HA_FLAG_MAJOR_CHANGE;
3524 
3525 #endif
3526             scb->ha_state.session_flags |= flags;
3527         }
3528         return scb->ha_state.session_flags;
3529     }
3530 
3531     return 0;
3532 }
3533 
getSessionFlags(void * scbptr)3534 static uint32_t getSessionFlags( void *scbptr )
3535 {
3536     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3537     if( scb )
3538         return scb->ha_state.session_flags;
3539 
3540     return 0;
3541 }
3542 
getSessionPolicy(void * scbptr,int policy_type)3543 static tSfPolicyId getSessionPolicy( void *scbptr, int policy_type )
3544 {
3545     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3546 
3547     if( policy_type == SNORT_NAP_POLICY )
3548         return scb->napPolicyId;
3549     else
3550         return scb->ipsPolicyId;
3551 }
3552 
setSessionPolicy(void * scbptr,int policy_type,tSfPolicyId id)3553 void setSessionPolicy( void *scbptr, int policy_type, tSfPolicyId id )
3554 {
3555     SessionControlBlock *scb = (SessionControlBlock *) scbptr;
3556 
3557     if ( scb == NULL )
3558         return;
3559 
3560     if( policy_type == SNORT_NAP_POLICY )
3561         scb->napPolicyId = id;
3562     else
3563         scb->ipsPolicyId = id;
3564 }
3565 
setSessionDeletionDelayed(void * scbptr,bool delay_session_deletion_flag)3566 static void setSessionDeletionDelayed( void *scbptr, bool delay_session_deletion_flag)
3567 {
3568     SessionControlBlock *scb = (SessionControlBlock *) scbptr;
3569     if ( scb == NULL )
3570         return;
3571 
3572     scb->is_session_deletion_delayed = delay_session_deletion_flag;
3573 }
3574 
isSessionDeletionDelayed(void * scbptr)3575 static bool isSessionDeletionDelayed( void *scbptr )
3576 {
3577     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3578     if( scb == NULL )
3579         return !STREAM_DELAY_SESSION_DELETION;
3580 
3581     return scb->is_session_deletion_delayed;
3582 }
3583 
ignoreChannel(const Packet * ctrlPkt,sfaddr_t * srcIP,uint16_t srcPort,sfaddr_t * dstIP,uint16_t dstPort,uint8_t protocol,uint32_t preprocId,char direction,char flags,struct _ExpectNode ** packetExpectedNode)3584 static int ignoreChannel( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort,
3585         sfaddr_t* dstIP, uint16_t dstPort, uint8_t protocol, uint32_t preprocId,
3586         char direction, char flags, struct _ExpectNode** packetExpectedNode )
3587 {
3588     return StreamExpectAddChannel( ctrlPkt, srcIP, srcPort, dstIP, dstPort, direction, flags,
3589             protocol, STREAM_EXPECTED_CHANNEL_TIMEOUT, 0, preprocId, NULL, NULL,
3590             packetExpectedNode );
3591 }
3592 
getIgnoreDirection(void * scbptr)3593 static int getIgnoreDirection( void *scbptr )
3594 {
3595     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3596     if( scb == NULL )
3597         return SSN_DIR_NONE;
3598 
3599     return scb->ha_state.ignore_direction;
3600 }
3601 
setIgnoreDirection(void * scbptr,int ignore_direction)3602 static int setIgnoreDirection( void *scbptr, int ignore_direction )
3603 {
3604     SessionControlBlock *scb = (SessionControlBlock *)scbptr;
3605     if( scb == NULL )
3606         return 0;
3607     if( scb->ha_state.ignore_direction != ignore_direction )
3608     {
3609         scb->ha_state.ignore_direction = ignore_direction;
3610 #ifdef ENABLE_HA
3611         ha_track_modify( scb );
3612 #endif
3613     }
3614     return scb->ha_state.ignore_direction;
3615 }
3616 
disableInspection(void * scbptr,Packet * p)3617 static void disableInspection( void *scbptr, Packet *p )
3618 {
3619     /*
3620      * Don't want to mess up PortScan by "dropping"
3621      * this packet.
3622      *
3623      * Also still want the perfmon to collect the stats.
3624      *
3625      * And don't want to do any detection with rules
3626      */
3627     DisableDetect( p );
3628     otn_tmp = NULL;
3629 }
3630 
stopInspection(void * scbptr,Packet * p,char dir,int32_t bytes,int response)3631 static void stopInspection( void * scbptr, Packet *p, char dir, int32_t bytes, int response )
3632 {
3633     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3634 
3635     if( scb == NULL )
3636         return;
3637 
3638     switch( dir )
3639     {
3640         case SSN_DIR_BOTH:
3641         case SSN_DIR_FROM_CLIENT:
3642         case SSN_DIR_FROM_SERVER:
3643             if( scb->ha_state.ignore_direction != dir )
3644             {
3645                 scb->ha_state.ignore_direction = dir;
3646 #ifdef ENABLE_HA
3647                 ha_track_modify( scb );
3648 #endif
3649             }
3650             break;
3651     }
3652 
3653     /* Flush any queued data on the client and/or server */
3654     if( scb->protocol == IPPROTO_TCP )
3655     {
3656         if( scb->ha_state.ignore_direction & SSN_DIR_TO_CLIENT )
3657             if( getSessionPlugins()->flush_client_stream != NULL )
3658                 getSessionPlugins()->flush_client_stream( p, scb );
3659 
3660         if( scb->ha_state.ignore_direction & SSN_DIR_TO_SERVER )
3661             if( getSessionPlugins()->flush_server_stream != NULL )
3662                 getSessionPlugins()->flush_server_stream( p, scb );
3663     }
3664 
3665     /* TODO: Handle bytes/response parameters */
3666 
3667     disableInspection( scb, p );
3668 }
3669 
resumeInspection(void * scbptr,char dir)3670 static void resumeInspection( void *scbptr, char dir )
3671 {
3672     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3673 
3674     if( !scb )
3675         return;
3676 
3677     switch( dir )
3678     {
3679         case SSN_DIR_BOTH:
3680         case SSN_DIR_FROM_CLIENT:
3681         case SSN_DIR_FROM_SERVER:
3682             if( scb->ha_state.ignore_direction & dir )
3683             {
3684                 scb->ha_state.ignore_direction &= ~dir;
3685 #ifdef ENABLE_HA
3686                 ha_track_modify( scb );
3687 #endif
3688             }
3689             break;
3690     }
3691 
3692 }
3693 
getPacketDirection(Packet * p)3694 static uint32_t getPacketDirection( Packet *p )
3695 {
3696     SessionControlBlock *scb;
3697 
3698     if( ( p == NULL ) || ( p->ssnptr == NULL ) )
3699         return 0;
3700 
3701     scb = ( SessionControlBlock * ) p->ssnptr;
3702 
3703     setPacketDirectionFlag( p, scb );
3704 
3705     return ( p->packet_flags & ( PKT_FROM_SERVER | PKT_FROM_CLIENT ) );
3706 }
3707 
dropTraffic(Packet * p,void * scbptr,char dir)3708 static void dropTraffic( Packet* p, void *scbptr, char dir )
3709 {
3710     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3711 
3712     if( scb == NULL )
3713         return;
3714 
3715     if( ( dir & SSN_DIR_FROM_CLIENT ) && !( scb->ha_state.session_flags & SSNFLAG_DROP_CLIENT ) )
3716     {
3717         scb->ha_state.session_flags |= SSNFLAG_DROP_CLIENT;
3718         if ( Active_PacketForceDropped() )
3719             scb->ha_state.session_flags |= SSNFLAG_FORCE_BLOCK;
3720 #ifdef ENABLE_HA
3721         scb->ha_flags |= ( HA_FLAG_MODIFIED | HA_FLAG_CRITICAL_CHANGE );
3722 #endif
3723     }
3724 
3725     if( ( dir & SSN_DIR_FROM_SERVER ) && !( scb->ha_state.session_flags & SSNFLAG_DROP_SERVER ) )
3726     {
3727         scb->ha_state.session_flags |= SSNFLAG_DROP_SERVER;
3728         if( Active_PacketForceDropped() )
3729             scb->ha_state.session_flags |= SSNFLAG_FORCE_BLOCK;
3730 #ifdef ENABLE_HA
3731         scb->ha_flags |= ( HA_FLAG_MODIFIED | HA_FLAG_CRITICAL_CHANGE );
3732 #endif
3733     }
3734 }
3735 
getFlowData(Packet * p)3736 static StreamFlowData *getFlowData( Packet *p )
3737 {
3738     SessionControlBlock *scb = ( SessionControlBlock * ) p->ssnptr;
3739 
3740     if ( ( scb == NULL ) || ( scb->flowdata == NULL ) )
3741         return NULL;
3742 
3743     return (StreamFlowData *)scb->flowdata->data;
3744 }
3745 
getPreprocessorStatusBit(void)3746 static uint16_t getPreprocessorStatusBit( void )
3747 {
3748     static uint16_t preproc_filter_status_bit = PORT_MONITOR_SESSION;
3749 
3750     preproc_filter_status_bit <<= 1;
3751 
3752     return preproc_filter_status_bit;
3753 }
3754 
setAppProtocolIdExpected(const Packet * ctrlPkt,sfaddr_t * srcIP,uint16_t srcPort,sfaddr_t * dstIP,uint16_t dstPort,uint8_t protocol,int16_t protoId,uint32_t preprocId,void * protoData,void (* protoDataFreeFn)(void *),struct _ExpectNode ** packetExpectedNode)3755 static int setAppProtocolIdExpected( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort,
3756         sfaddr_t* dstIP, uint16_t dstPort, uint8_t protocol, int16_t protoId, uint32_t preprocId,
3757         void *protoData, void (*protoDataFreeFn)(void*), struct _ExpectNode** packetExpectedNode)
3758 {
3759     return StreamExpectAddChannel( ctrlPkt, srcIP, srcPort, dstIP, dstPort, SSN_DIR_BOTH, 0, protocol,
3760             STREAM_EXPECTED_CHANNEL_TIMEOUT, protoId, preprocId, protoData, protoDataFreeFn,
3761             packetExpectedNode );
3762 }
3763 
3764 #ifdef TARGET_BASED
setIpProtocol(SessionControlBlock * scb)3765 void setIpProtocol( SessionControlBlock *scb )
3766 {
3767     switch (scb->protocol)
3768     {
3769         case IPPROTO_TCP:
3770             if (scb->ha_state.ipprotocol != protocolReferenceTCP)
3771             {
3772                 scb->ha_state.ipprotocol = protocolReferenceTCP;
3773 #ifdef ENABLE_HA
3774                 ha_track_modify(scb);
3775 #endif
3776             }
3777             break;
3778         case IPPROTO_UDP:
3779             if (scb->ha_state.ipprotocol != protocolReferenceUDP)
3780             {
3781                 scb->ha_state.ipprotocol = protocolReferenceUDP;
3782 #ifdef ENABLE_HA
3783                 ha_track_modify(scb);
3784 #endif
3785             }
3786             break;
3787         case IPPROTO_ICMP:
3788             if (scb->ha_state.ipprotocol != protocolReferenceICMP)
3789             {
3790                 scb->ha_state.ipprotocol = protocolReferenceICMP;
3791 #ifdef ENABLE_HA
3792                 ha_track_modify(scb);
3793 #endif
3794             }
3795             break;
3796     }
3797 }
3798 
setAppProtocolIdFromHostEntry(SessionControlBlock * scb,HostAttributeEntry * host_entry,int direction)3799 void setAppProtocolIdFromHostEntry( SessionControlBlock *scb, HostAttributeEntry *host_entry, int direction )
3800 {
3801     int16_t application_protocol;
3802 
3803     if ( ( scb == NULL ) || ( host_entry == NULL ) )
3804         return;
3805 
3806     /* Cool, its already set! */
3807     if( scb->ha_state.application_protocol != 0 )
3808         return;
3809 
3810     if( scb->ha_state.ipprotocol == 0 )
3811     {
3812         setIpProtocol( scb );
3813     }
3814 
3815     if( direction == SSN_DIR_FROM_SERVER )
3816     {
3817         application_protocol = getApplicationProtocolId( host_entry, scb->ha_state.ipprotocol,
3818                 ntohs( scb->server_port ), SFAT_SERVICE );
3819     }
3820     else
3821     {
3822         application_protocol = getApplicationProtocolId( host_entry, scb->ha_state.ipprotocol,
3823                 ntohs( scb->client_port ), SFAT_SERVICE );
3824     }
3825 
3826     if( scb->ha_state.application_protocol != application_protocol )
3827     {
3828         scb->ha_state.application_protocol = application_protocol;
3829 #ifdef ENABLE_HA
3830         ha_track_modify( scb );
3831 #endif
3832         // modify enabled preprocs mask to include only those always run and the ones
3833         // registered for this application id
3834         scb->enabled_pps = appHandlerDispatchMask[ application_protocol ]
3835                            |
3836                            ( scb->enabled_pps & ( PP_CLASS_NETWORK | PP_CLASS_NGFW ) );
3837 
3838     }
3839 }
3840 
3841 #ifdef TARGET_BASED
3842 #ifdef ACTIVE_RESPONSE
initActiveResponse(Packet * p,void * pv)3843 static void initActiveResponse( Packet *p, void *pv )
3844 {
3845     SessionControlBlock *scb = ( SessionControlBlock * ) pv;
3846 
3847     if ( scb == NULL )
3848         return;
3849 
3850     scb->response_count = 1;
3851 
3852     if ( session_configuration->max_active_responses > 1 )
3853    {
3854 #if defined(DAQ_CAPA_CST_TIMEOUT)
3855      if (!Daq_Capa_Timeout)
3856 #endif
3857         setSessionExpirationTime( p, scb, session_configuration->min_response_seconds );
3858 }
3859 }
3860 #endif
3861 #endif
3862 
3863 #ifdef TARGET_BASED
getHopLimit(void * pv,char dir,int outer)3864 static uint8_t getHopLimit( void* pv, char dir, int outer )
3865 {
3866     SessionControlBlock *scb = (SessionControlBlock*)pv;
3867 
3868     if ( scb == NULL )
3869         return 255;
3870 
3871     if ( SSN_DIR_FROM_CLIENT == dir )
3872         return outer ? scb->outer_client_ttl : scb->inner_client_ttl;
3873 
3874     return outer ? scb->outer_server_ttl : scb->inner_server_ttl;
3875 }
3876 #endif
3877 
3878 
registerApplicationHandler(uint32_t preproc_id,int16_t app_id)3879 static void registerApplicationHandler( uint32_t preproc_id, int16_t app_id )
3880 {
3881 
3882     if( app_id < 0 )
3883     {
3884         WarningMessage( "(%s)(%d) Invalid application id: %d.  Application handler registration failed.",
3885                 __FILE__, __LINE__, app_id );
3886         return;
3887     }
3888 
3889     // set bit for this preproc in the dispatch mask
3890     appHandlerDispatchMask[ app_id ] |= ( UINT64_C(1) << preproc_id );
3891 }
3892 
getAppProtocolId(void * scbptr)3893 static int16_t getAppProtocolId( void *scbptr )
3894 {
3895     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3896     /* Not caching the source and dest host_entry in the session so we can
3897      * swap the table out after processing this packet if we need
3898      * to.  */
3899     HostAttributeEntry *host_entry = NULL;
3900     int16_t protocol = 0;
3901 
3902     if( scb == NULL )
3903         return protocol;
3904 
3905     if( scb->ha_state.application_protocol == -1 )
3906         return 0;
3907 
3908     if( scb->ha_state.application_protocol != 0 )
3909         return scb->ha_state.application_protocol;
3910 
3911     if( !IsAdaptiveConfigured( ) )
3912         return scb->ha_state.application_protocol;
3913 
3914     if( scb->ha_state.ipprotocol == 0 )
3915     {
3916         setIpProtocol(scb);
3917     }
3918 
3919     host_entry = SFAT_LookupHostEntryByIP(IP_ARG(scb->server_ip));
3920     if( host_entry )
3921     {
3922         setAppProtocolIdFromHostEntry(scb, host_entry, SSN_DIR_FROM_SERVER);
3923 
3924         if( scb->ha_state.application_protocol != 0 )
3925         {
3926             return scb->ha_state.application_protocol;
3927         }
3928     }
3929 
3930     host_entry = SFAT_LookupHostEntryByIP( IP_ARG( scb->client_ip ) );
3931     if( host_entry )
3932     {
3933         setAppProtocolIdFromHostEntry( scb, host_entry, SSN_DIR_FROM_CLIENT );
3934         if( scb->ha_state.application_protocol != 0 )
3935         {
3936             return scb->ha_state.application_protocol;
3937         }
3938     }
3939 
3940     scb->ha_state.application_protocol = -1;
3941 
3942     return scb->ha_state.application_protocol;
3943 }
3944 
setAppProtocolId(void * scbptr,int16_t id)3945 static int16_t setAppProtocolId( void *scbptr, int16_t id )
3946 {
3947     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3948     if( scb == NULL )
3949         return 0;
3950 
3951     // modify enabled preprocs mask to include only those always run and the ones
3952     // registered for this application id
3953     scb->enabled_pps = appHandlerDispatchMask[ id ] | ( scb->enabled_pps & ( PP_CLASS_NETWORK | PP_CLASS_NGFW ) );
3954 
3955     if( !IsAdaptiveConfigured( ) )
3956         return 0;
3957 
3958     if( scb->ha_state.application_protocol != id )
3959     {
3960         scb->ha_state.application_protocol = id;
3961 #ifdef ENABLE_HA
3962         ha_track_modify( scb );
3963 #endif
3964     }
3965 
3966     if( !scb->ha_state.ipprotocol )
3967         setIpProtocol( scb );
3968 
3969     if( !(scb->protocol == IPPROTO_TCP) || !StreamIsSessionDecryptedTcp( scb ) )
3970         SFAT_UpdateApplicationProtocol( IP_ARG( scb->server_ip ), ntohs( scb->server_port ),
3971                 scb->ha_state.ipprotocol, id );
3972 
3973     if( scb->protocol == IPPROTO_TCP &&
3974             scb->ha_state.application_protocol > 0 )
3975         set_service_based_flush_policy(scb);
3976 
3977     return id;
3978 }
3979 
getSessionIpAddress(void * scbptr,uint32_t direction)3980 static sfaddr_t* getSessionIpAddress( void *scbptr, uint32_t direction )
3981 {
3982     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3983 
3984     if( scb != NULL )
3985     {
3986         switch( direction )
3987         {
3988             case SSN_DIR_FROM_SERVER:
3989                 return ( sfaddr_t* ) ( &( ( SessionControlBlock * ) scb)->server_ip );
3990 
3991             case SSN_DIR_FROM_CLIENT:
3992                 return ( sfaddr_t* ) ( &( ( SessionControlBlock * ) scb)->client_ip );
3993 
3994             default:
3995                 break;
3996         }
3997     }
3998 
3999     return NULL;
4000 }
4001 
getSessionPorts(void * scbptr,uint16_t * client_port,uint16_t * server_port)4002 static void getSessionPorts( void *scbptr, uint16_t *client_port, uint16_t *server_port )
4003 {
4004     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
4005 
4006     if( scb != NULL )
4007     {
4008         if(client_port)
4009         {
4010             *client_port = ntohs(scb->client_port);
4011         }
4012         if(server_port)
4013         {
4014             *server_port = ntohs(scb->server_port);
4015         }
4016     }
4017 
4018     return;
4019 }
4020 #endif
4021 
getMaxSessions(tSfPolicyId policyId,StreamSessionLimits * limits)4022 static void getMaxSessions( tSfPolicyId policyId, StreamSessionLimits* limits )
4023 {
4024     if( session_configuration )
4025     {
4026         limits->tcp_session_limit = session_configuration->track_tcp_sessions ?
4027             session_configuration->max_tcp_sessions : 0;
4028 
4029         limits->udp_session_limit = session_configuration->track_udp_sessions ?
4030             session_configuration->max_udp_sessions : 0;
4031 
4032         limits->icmp_session_limit = session_configuration->track_icmp_sessions ?
4033             session_configuration->max_icmp_sessions : 0;
4034 
4035         limits->ip_session_limit = session_configuration->track_ip_sessions ?
4036             session_configuration->max_ip_sessions : 0;
4037     }
4038     else
4039         memset( limits, 0, sizeof( *limits ) );
4040 }
4041 
disablePreprocForSession(void * scbptr,uint32_t preproc_id)4042 static void disablePreprocForSession( void *scbptr, uint32_t preproc_id )
4043 {
4044     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
4045 
4046     if( scb != NULL )
4047         scb->enabled_pps &= ~( UINT64_C(1) << preproc_id );
4048 }
4049 
4050 
enablePreprocForPort(SnortConfig * sc,uint32_t preproc_id,uint32_t proto,uint16_t port)4051 static void enablePreprocForPort( SnortConfig *sc, uint32_t preproc_id, uint32_t proto, uint16_t port )
4052 {
4053     tSfPolicyId policy_id = getParserPolicy( sc );
4054     SnortPolicy *policy = sc->targeted_policies[ policy_id ];
4055 
4056     if( policy == NULL )
4057     {
4058         WarningMessage( "Invalid policy id: %d.  No snort policy allocated", policy_id );
4059         return;
4060     }
4061 
4062     policy->pp_enabled[ port ] |= ( UINT64_C(1) << preproc_id );
4063 }
4064 
enablePreprocAllPorts(SnortConfig * sc,uint32_t preproc_id,uint32_t proto)4065 static void enablePreprocAllPorts( SnortConfig *sc, uint32_t preproc_id, uint32_t proto )
4066 {
4067     tSfPolicyId policy_id = getParserPolicy( sc );
4068     SnortPolicy *policy = sc->targeted_policies[ policy_id ];
4069     uint32_t port;
4070 
4071     if( policy == NULL )
4072     {
4073         WarningMessage( "Invalid policy id: %d.  No snort policy allocated", policy_id );
4074         return;
4075     }
4076 
4077     for( port = 0; port < MAX_PORTS; port++ )
4078         policy->pp_enabled[ port ] |= ( UINT64_C(1) << preproc_id );
4079 }
4080 
enablePreprocAllPortsAllPolicies(SnortConfig * sc,uint32_t preproc_id,uint32_t proto)4081 static void enablePreprocAllPortsAllPolicies( SnortConfig *sc, uint32_t preproc_id, uint32_t proto )
4082 {
4083     uint32_t i;
4084 
4085     for( i = 0; i < sc->num_policies_allocated; i++ )
4086     if( ( sc->targeted_policies[ i ] != NULL ) && ( sc->targeted_policies[ i ]->num_preprocs > 0 ) )
4087     {
4088         setParserPolicy( sc, i );
4089         enablePreprocAllPorts( sc, preproc_id, proto );
4090     }
4091 }
4092 
isPreprocEnabledForPort(uint32_t preproc_id,uint16_t port)4093 static bool isPreprocEnabledForPort( uint32_t preproc_id, uint16_t port )
4094 {
4095     tSfPolicyId policy_id = getNapRuntimePolicy();
4096     SnortPolicy *policy = snort_conf->targeted_policies[ policy_id ];
4097 
4098    if( policy->pp_enabled[ port ] & ( UINT64_C(1) << preproc_id ) )
4099        return true;
4100    else
4101        return false;
4102 }
4103 
registerNapSelector(nap_selector nap_selector_func)4104 static void registerNapSelector( nap_selector nap_selector_func )
4105 {
4106    struct session_plugins *pfunks = getSessionPlugins( );
4107 
4108     if( nap_selector_func != NULL )
4109         pfunks->select_session_nap = nap_selector_func;
4110 }
4111 
registerGetHttpXffPrecedence(GetHttpXffPrecedenceFunc fn)4112 static void registerGetHttpXffPrecedence(GetHttpXffPrecedenceFunc fn)
4113 {
4114     if (!getHttpXffPrecedenceFunc) getHttpXffPrecedenceFunc = fn;
4115 }
4116 
getHttpXffPrecedence(void * ssn,uint32_t flags,int * nFields)4117 static char** getHttpXffPrecedence(void* ssn, uint32_t flags, int* nFields)
4118 {
4119     if (getHttpXffPrecedenceFunc) return getHttpXffPrecedenceFunc(ssn, flags, nFields);
4120     else return NULL;
4121 }
4122 
setReputationUpdateCount(void * scbptr,uint8_t count)4123 static void setReputationUpdateCount (void *scbptr, uint8_t count)
4124 {
4125     SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
4126     if ( scb )
4127         scb->iprep_update_counter = count;
4128 }
4129 
4130 #ifdef SNORT_RELOAD
reloadSessionConfiguration(struct _SnortConfig * sc,char * args,void ** new_config)4131 static void reloadSessionConfiguration( struct _SnortConfig *sc, char *args, void **new_config )
4132 {
4133     SessionConfiguration *session_config = ( SessionConfiguration * ) *new_config;
4134 
4135     // session config is only in default policy... fatal error if not parsing default
4136     if( getParserPolicy( sc ) != getDefaultPolicy( ) )
4137     {
4138         FatalError("%s(%d) Session configuration included in non-default policy.\n", __FILE__, __LINE__);
4139     }
4140 
4141     if ( session_config == NULL )
4142     {
4143         session_config = initSessionConfiguration( );
4144         parseSessionConfiguration( session_config, args );
4145         *new_config = session_config;
4146 
4147         session_reload_configuration = session_config;
4148 
4149         sc->run_flags |= RUN_FLAG__STATEFUL;
4150     }
4151     else
4152     {
4153 #if 0
4154         // EDM-TBD
4155         FatalError("stream5_global must only be configured once.\n");
4156 #else
4157         WarningMessage("stream5_global must only be configured once. Ignoring this configuration element\n");
4158         *new_config = NULL;
4159 #endif
4160     }
4161 }
4162 
SessionReload(SessionCache * lws_cache,uint32_t max_sessions,uint32_t aggressiveTimeout,uint32_t nominalTimeout,const char * name)4163 void SessionReload(SessionCache* lws_cache, uint32_t max_sessions,
4164                    uint32_t aggressiveTimeout, uint32_t nominalTimeout
4165 #ifdef REG_TEST
4166                    , const char* name
4167 #endif
4168                    )
4169 {
4170     if (lws_cache)
4171     {
4172 #ifdef REG_TEST
4173         if (REG_TEST_FLAG_SESSION_RELOAD & getRegTestFlags())
4174         {
4175             const char* excessCountStr;
4176             excessCountStr = (sfxhash_total_count(lws_cache->hashTable) > max_sessions) ? "" : "no ";
4177             if (lws_cache->protocol_session_pool)
4178             {
4179                 const char *excessProtocolCountStr;
4180                 excessProtocolCountStr = (mempool_numTotalBuckets(lws_cache->protocol_session_pool) > max_sessions) ? "" : "no ";
4181                 printf("Setting %s max sessions to %u with %sexcess sessions and %sexcess protocol entries\n",
4182                        name, max_sessions, excessCountStr, excessProtocolCountStr);
4183             }
4184             else
4185             {
4186                 printf("Setting %s max sessions to %u with %sexcess sessions\n",
4187                        name, max_sessions, excessCountStr);
4188             }
4189             printf("Setting %s aggressive timeout to %u and nominal timeout to %u\n",
4190                    name, aggressiveTimeout, nominalTimeout);
4191         }
4192 #endif
4193 #if defined(DAQ_CAPA_CST_TIMEOUT)
4194         if (!Daq_Capa_Timeout)
4195 #endif
4196         {
4197            lws_cache->timeoutNominal = nominalTimeout;
4198         }
4199         lws_cache->timeoutAggressive = aggressiveTimeout;
4200         sfxhash_set_max_nodes(lws_cache->hashTable, max_sessions);
4201         if (lws_cache->protocol_session_pool)
4202             mempool_setNumObjects(lws_cache->protocol_session_pool, max_sessions);
4203     }
4204 }
4205 
SessionProtocolReloadAdjust(SessionCache * lws_cache,uint32_t max_sessions,unsigned maxWork,uint32_t memcap,const char * name)4206 unsigned SessionProtocolReloadAdjust(SessionCache* lws_cache, uint32_t max_sessions,
4207                                      unsigned maxWork, uint32_t memcap
4208 #ifdef REG_TEST
4209                                      , const char* name
4210 #endif
4211                                      )
4212 {
4213     if (lws_cache)
4214     {
4215         SessionControlBlock *scb;
4216 
4217         for (; maxWork && sfxhash_total_count(lws_cache->hashTable) > max_sessions; maxWork--)
4218         {
4219             if (sfxhash_free_anr(lws_cache->hashTable) != SFXHASH_OK)
4220             {
4221                 scb = (SessionControlBlock *)sfxhash_lru(lws_cache->hashTable);
4222                 if (scb)
4223                 {
4224                     scb->ha_state.session_flags |= SSNFLAG_PRUNED;
4225                     deleteSession(lws_cache, scb, "reload adjust", false);
4226                 }
4227                 else
4228                     break;
4229             }
4230         }
4231 
4232         if (!maxWork)
4233             return 0;
4234 
4235         if (memcap)
4236         {
4237             while (maxWork && session_mem_in_use > memcap)
4238             {
4239                 scb = (SessionControlBlock *)sfxhash_lru(lws_cache->hashTable);
4240                 if (scb)
4241                 {
4242                     if (isSessionBlocked(scb))
4243                         moveHashNodeToFront(lws_cache);
4244                     else
4245                     {
4246                         scb->ha_state.session_flags |= SSNFLAG_PRUNED;
4247                         deleteSession(lws_cache, scb, "reload adjust", false);
4248                         maxWork--;
4249                     }
4250                 }
4251                 else
4252                     break;
4253             }
4254 
4255             if (!maxWork)
4256                 return 0;
4257         }
4258 
4259         if (lws_cache->protocol_session_pool)
4260         {
4261             for (; maxWork && mempool_numTotalBuckets(lws_cache->protocol_session_pool) > max_sessions; maxWork--)
4262             {
4263                 if (mempool_free_bucket(lws_cache->protocol_session_pool))
4264                     break;
4265             }
4266         }
4267     }
4268     return maxWork;
4269 }
4270 
SessionReloadAdjust(bool idle,tSfPolicyId raPolicyId,void * userData)4271 static bool SessionReloadAdjust(bool idle, tSfPolicyId raPolicyId, void* userData)
4272 {
4273     unsigned initialMaxWork = idle ? 512 : 5;
4274     unsigned maxWork;
4275 
4276     Active_Suspend();
4277     maxWork = SessionTCPReloadAdjust(initialMaxWork);
4278 
4279     if (!maxWork)
4280     {
4281         Active_Resume();
4282         return false;
4283     }
4284 
4285     maxWork = SessionUDPReloadAdjust(maxWork);
4286 
4287     if (!maxWork)
4288     {
4289         Active_Resume();
4290         return false;
4291     }
4292 
4293     maxWork = SessionIPReloadAdjust(maxWork);
4294 
4295     if (!maxWork)
4296     {
4297         Active_Resume();
4298         return false;
4299     }
4300 
4301     maxWork = SessionICMPReloadAdjust(maxWork);
4302 
4303     if (!maxWork)
4304     {
4305         Active_Resume();
4306         return false;
4307     }
4308 
4309     for (; maxWork && mempool_numTotalBuckets(&sessionFlowMempool) > session_configuration->max_sessions; maxWork--)
4310     {
4311         if (mempool_free_bucket(&sessionFlowMempool))
4312             break;
4313     }
4314 
4315 #ifdef REG_TEST
4316     if (REG_TEST_FLAG_SESSION_RELOAD & getRegTestFlags())
4317     {
4318         if (maxWork == initialMaxWork)
4319         {
4320             SessionCache* lws_cache;
4321 
4322             if ((lws_cache = proto_session_caches[SESSION_PROTO_TCP]))
4323             {
4324                 printf("TCP session count %u, protocol count %u\n",
4325                        sfxhash_total_count(lws_cache->hashTable),
4326                        mempool_numTotalBuckets(lws_cache->protocol_session_pool));
4327                 printf("TCP aggressive timeout %u, nominal timeout %u\n",
4328                        lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4329             }
4330             if ((lws_cache = proto_session_caches[SESSION_PROTO_UDP]))
4331             {
4332                 printf("UDP session count %u, protocol count %u\n",
4333                        sfxhash_total_count(lws_cache->hashTable),
4334                        mempool_numTotalBuckets(lws_cache->protocol_session_pool));
4335                 printf("UDP aggressive timeout %u, nominal timeout %u\n",
4336                        lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4337             }
4338             if ((lws_cache = proto_session_caches[SESSION_PROTO_ICMP]))
4339             {
4340                 printf("ICMP session count %u, protocol count %u\n",
4341                        sfxhash_total_count(lws_cache->hashTable),
4342                        mempool_numTotalBuckets(lws_cache->protocol_session_pool));
4343                 printf("ICMP aggressive timeout %u, nominal timeout %u\n",
4344                        lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4345             }
4346             if ((lws_cache = proto_session_caches[SESSION_PROTO_IP]))
4347             {
4348                 printf("IP session count %u\n",
4349                        sfxhash_total_count(lws_cache->hashTable));
4350                 printf("IP aggressive timeout %u, nominal timeout %u\n",
4351                        lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4352             }
4353             printf("Flow pool count %u\n", mempool_numTotalBuckets(&sessionFlowMempool));
4354 
4355             printf("Memory in use %s the memory cap\n",
4356                    (session_mem_in_use > session_configuration->memcap) ?
4357                         "greater than" : "less than or equal to");
4358             fflush(stdout);
4359         }
4360     }
4361 #endif
4362     return (maxWork == initialMaxWork) ? true : false;
4363 }
4364 
4365 #ifdef ENABLE_HA
verifyConfigOptionUnchanged(uint32_t new,uint32_t old,char * name,SessionConfiguration * config)4366 static bool verifyConfigOptionUnchanged( uint32_t new, uint32_t old, char *name, SessionConfiguration *config )
4367 {
4368     if( old == new )
4369         return false;
4370 
4371     ErrorMessage("Session Reload: Changing \"%s\" requires a restart.\n", name);
4372     return true;
4373 }
4374 #endif
4375 
verifyReloadedSessionConfiguration(struct _SnortConfig * sc,void * swap_config)4376 static int verifyReloadedSessionConfiguration( struct _SnortConfig *sc, void *swap_config )
4377 {
4378     static const char* SESSION_RELOAD = "Session";
4379     SessionConfiguration *ssc = ( SessionConfiguration * ) swap_config;
4380     tSfPolicyId tmp_policy_id = getParserPolicy( sc );
4381     bool restart_required = false;
4382 
4383     if( ( session_configuration == NULL ) || ( ssc == NULL ) )
4384     {
4385         FatalError("%s(%d) Session config is NULL.\n", __FILE__, __LINE__);
4386     }
4387 
4388     if( ( ssc->track_tcp_sessions != session_configuration->track_tcp_sessions ) ||
4389             ( ssc->track_udp_sessions != session_configuration->track_udp_sessions ) ||
4390             ( ssc->track_icmp_sessions != session_configuration->track_icmp_sessions ) ||
4391             ( ssc->track_ip_sessions != session_configuration->track_ip_sessions ) )
4392     {
4393         ErrorMessage("Session Reload: Changing tracking of TCP, UDP ICMP, or IP "
4394                 "sessions requires a restart.\n");
4395         return -1;
4396     }
4397 
4398     if (ssc->track_tcp_sessions != STREAM_TRACK_YES)
4399     {
4400         ssc->memcap = 0;
4401         ssc->max_tcp_sessions = 0;
4402     }
4403     if (ssc->track_udp_sessions != STREAM_TRACK_YES)
4404         ssc->max_udp_sessions = 0;
4405     if (ssc->track_icmp_sessions != STREAM_TRACK_YES)
4406         ssc->max_icmp_sessions = 0;
4407     if (ssc->track_ip_sessions != STREAM_TRACK_YES)
4408         ssc->max_ip_sessions = 0;
4409 
4410 #ifdef ENABLE_HA
4411     restart_required |= verifyConfigOptionUnchanged( ssc->enable_ha,
4412             session_configuration->enable_ha,
4413             "enable_ha", ssc );
4414 #endif
4415 
4416     if( restart_required )
4417     {
4418         // options were changed that require a restart, let's get out of here...
4419         ErrorMessage("Session Reload: Verify Failed, Restart Required\n");
4420         return -1;
4421     }
4422 
4423     setParserPolicy( sc, getDefaultPolicy()  );
4424     enablePreprocAllPorts( sc, PP_SESSION, PROTO_BIT__ALL );
4425     AddFuncToPreprocList(sc, sessionPacketProcessor, PP_SESSION_PRIORITY, PP_SESSION, PROTO_BIT__ALL);
4426     setParserPolicy( sc, tmp_policy_id );
4427 
4428     initializeMaxExpectedFlows( session_configuration );
4429 
4430     ssc->numSnortPolicies = sc->num_policies_allocated;
4431     ssc->policy_ref_count = SnortPreprocAlloc( sc->num_policies_allocated,
4432                                    sizeof( uint32_t ), PP_STREAM,
4433                                    PP_MEM_CATEGORY_SESSION );
4434     if (!ssc->policy_ref_count)
4435         FatalError("%s(%d) policy_ref_count allocation failed.\n", __FILE__, __LINE__);
4436 
4437     ssc->max_sessions = ssc->max_tcp_sessions + ssc->max_udp_sessions +
4438                         ssc->max_icmp_sessions + ssc->max_ip_sessions;
4439     if (session_configuration->memcap > ssc->memcap ||
4440         session_configuration->max_udp_sessions > ssc->max_udp_sessions ||
4441         session_configuration->max_tcp_sessions > ssc->max_tcp_sessions ||
4442         session_configuration->max_ip_sessions > ssc->max_ip_sessions ||
4443         session_configuration->max_icmp_sessions > ssc->max_icmp_sessions)
4444     {
4445         ReloadAdjustSessionRegister(sc, SESSION_RELOAD, tmp_policy_id,
4446                                     &SessionReloadAdjust, NULL, NULL);
4447     }
4448     printSessionConfiguration(session_configuration);
4449 
4450     return 0;
4451 }
4452 
activateSessionConfiguration(struct _SnortConfig * sc,void * data)4453 static void *activateSessionConfiguration( struct _SnortConfig *sc, void *data )
4454 {
4455     SessionConfiguration *old_config = NULL;
4456     unsigned int i;
4457 
4458     if( data == NULL )
4459         return NULL;
4460 
4461     old_config = session_configuration;
4462     session_configuration = ( SessionConfiguration * ) data;
4463 
4464     SessionTCPReload(session_configuration->max_tcp_sessions,
4465                      session_configuration->tcp_cache_pruning_timeout,
4466                      session_configuration->tcp_cache_nominal_timeout);
4467     SessionUDPReload(session_configuration->max_udp_sessions,
4468                      session_configuration->udp_cache_pruning_timeout,
4469                      session_configuration->udp_cache_nominal_timeout);
4470     SessionICMPReload(session_configuration->max_icmp_sessions,
4471                       30, 3 * 30);
4472     SessionIPReload(session_configuration->max_ip_sessions,
4473                     30, 3 * 30);
4474 #ifdef REG_TEST
4475     if (REG_TEST_FLAG_SESSION_RELOAD & getRegTestFlags())
4476     {
4477         const char* excessStr;
4478 
4479         excessStr = (mempool_numTotalBuckets(&sessionFlowMempool) > session_configuration->max_sessions) ? "" : "no ";
4480         printf("Setting flow pool max sessions to %u with %sexcess entries\n",
4481                session_configuration->max_sessions, excessStr);
4482         excessStr = (session_mem_in_use > session_configuration->memcap) ? "" : "no ";
4483         printf("Setting memcap to %u with %sexcess memory\n",
4484                session_configuration->memcap, excessStr);
4485     }
4486 #endif
4487     mempool_setNumObjects(&sessionFlowMempool, session_configuration->max_sessions);
4488     session_reload_configuration = NULL;
4489 
4490 #ifdef REG_TEST
4491     fflush(stdout);
4492 #endif
4493 
4494     for( i = 0; i < old_config->numSnortPolicies; i++ )
4495     {
4496         if( old_config->policy_ref_count[ i ] > 0 )
4497         {
4498             // some sessions still using config from old policy...
4499             LogMessage("Session Reload: Reference Count Non-zero for old configuration.\n");
4500             return NULL;
4501         }
4502     }
4503 
4504     return old_config;
4505 }
4506 
freeSessionConfiguration(void * data)4507 static void freeSessionConfiguration( void *data )
4508 {
4509     if( data == NULL )
4510         return;
4511 
4512     LogMessage("Session Reload: Freeing Session Configuration Memory.\n");
4513     SessionFreeConfig( ( SessionConfiguration * )  data );
4514 }
4515 
4516 #endif
4517 
4518