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