"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/preprocessors/Stream6/snort_stream_ip.c" (16 Oct 2020, 14825 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "snort_stream_ip.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /****************************************************************************
2 *
3 * Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
4 * Copyright (C) 2005-2013 Sourcefire, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License Version 2 as
8 * published by the Free Software Foundation. You may not use, modify or
9 * distribute this program under any other version of the GNU General
10 * Public License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 * ***************************************************************************/
22
23 /*
24 * @file snort_stream_ip.c
25 * @author Russ Combs <rcombs@sourcefire.com>
26 *
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "active.h"
34 #include "decode.h"
35 #include "detect.h"
36 #include "mstring.h"
37 #include "parser.h"
38 #include "profiler.h"
39 #include "sfPolicy.h"
40 #include "sfxhash.h"
41 #include "sf_types.h"
42 #include "snort_debug.h"
43
44 #include "spp_session.h"
45 #include "session_api.h"
46 #include "snort_session.h"
47
48 #include "snort_stream_ip.h"
49 #include "session_expect.h"
50 #include "stream5_ha.h"
51 #include "util.h"
52
53 #include "reg_test.h"
54
55 #ifdef PERF_PROFILING
56 PreprocStats s5IpPerfStats;
57 #endif
58
59 static SessionCache* ip_lws_cache = NULL;
60
61 //-------------------------------------------------------------------------
62 // private methods
63 //-------------------------------------------------------------------------
64
65 static void StreamPrintIpConfig (StreamIpPolicy* policy)
66 {
67 LogMessage("Stream IP Policy config:\n");
68 LogMessage(" Timeout: %d seconds\n", policy->session_timeout);
69
70 }
71
72 static void StreamParseIpArgs (char* args, StreamIpPolicy* policy)
73 {
74 char* *toks;
75 int num_toks;
76 int i;
77
78 policy->session_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
79
80 if ( !args || !*args )
81 return;
82
83 toks = mSplit(args, ",", 0, &num_toks, 0);
84
85 for (i = 0; i < num_toks; i++)
86 {
87 int s_toks;
88 char* *stoks = mSplit(toks[i], " ", 2, &s_toks, 0);
89
90 if (s_toks == 0)
91 {
92 ParseError("Missing parameter in Stream IP config.\n");
93 }
94
95 if(!strcasecmp(stoks[0], "timeout"))
96 {
97 char* endPtr = NULL;
98
99 if(stoks[1])
100 {
101 policy->session_timeout = strtoul(stoks[1], &endPtr, 10);
102 }
103
104 if (!stoks[1] || (endPtr == &stoks[1][0]))
105 {
106 ParseError("Invalid timeout in config file. Integer parameter required.\n");
107 }
108
109 if ((policy->session_timeout > STREAM_MAX_SSN_TIMEOUT) ||
110 (policy->session_timeout < STREAM_MIN_SSN_TIMEOUT))
111 {
112 ParseError("Invalid timeout in config file. Must be between %d and %d\n",
113 STREAM_MIN_SSN_TIMEOUT, STREAM_MAX_SSN_TIMEOUT);
114 }
115 if (s_toks > 2)
116 {
117 ParseError("Invalid Stream IP Policy option. Missing comma?\n");
118 }
119 }
120 else
121 {
122 ParseError("Invalid Stream IP policy option\n");
123 }
124
125 mSplitFree(&stoks, s_toks);
126 }
127
128 mSplitFree(&toks, num_toks);
129 }
130
131 void IpSessionCleanup (void* ssn)
132 {
133 SessionControlBlock *scb = ( SessionControlBlock * ) ssn;
134
135 if (scb->ha_state.session_flags & SSNFLAG_PRUNED)
136 {
137 CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED);
138 }
139 else if (scb->ha_state.session_flags & SSNFLAG_TIMEDOUT)
140 {
141 CloseStreamSession(&sfBase, SESSION_CLOSED_TIMEDOUT);
142 }
143 else
144 {
145 CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY);
146 }
147
148 StreamResetFlowBits(scb);
149 session_api->free_application_data(scb);
150
151 scb->ha_state.session_flags = SSNFLAG_NONE;
152 scb->session_state = STREAM_STATE_NONE;
153
154 scb->expire_time = 0;
155 scb->ha_state.ignore_direction = 0;
156 s5stats.active_ip_sessions--;
157 }
158
159
160 #ifdef ENABLE_HA
161
162 //-------------------------------------------------------------------------
163 // ip ha stuff
164 //-------------------------------------------------------------------------
165
166 SessionControlBlock *GetLWIpSession (const SessionKey *key)
167 {
168 return session_api->get_session_by_key(ip_lws_cache, key);
169 }
170
171 static SessionControlBlock *StreamIPCreateSession (const SessionKey *key)
172 {
173 setNapRuntimePolicy(getDefaultPolicy());
174
175 SessionControlBlock *scb = session_api->create_session(ip_lws_cache, NULL, key);
176 if (scb)
177 s5stats.active_ip_sessions++;
178
179 return scb;
180 }
181
182 static int StreamIPDeleteSession (const SessionKey *key)
183 {
184 SessionControlBlock *scb = session_api->get_session_by_key(ip_lws_cache, key);
185
186 if( scb != NULL )
187 {
188 if( StreamSetRuntimeConfiguration(scb, scb->protocol) == 0 )
189 {
190 session_api->delete_session(ip_lws_cache, scb, "ha sync", false);
191 s5stats.active_ip_sessions--;
192 }
193 else
194 WarningMessage(" WARNING: Attempt to delete an IP Session when no valid runtime configuration\n" );
195 }
196
197 return 0;
198 }
199
200
201 static HA_Api ha_ip_api = {
202 /*.get_lws = */ GetLWIpSession,
203
204 /*.create_session = */ StreamIPCreateSession,
205 /*.deactivate_session = */ NULL,
206 /*.delete_session = */ StreamIPDeleteSession,
207 };
208
209 #endif
210
211 //-------------------------------------------------------------------------
212 // public methods
213 //-------------------------------------------------------------------------
214
215 void StreamInitIp( void )
216 {
217 if(ip_lws_cache == NULL)
218 {
219 ip_lws_cache = session_api->init_session_cache( SESSION_PROTO_IP,
220 0, // NO session control blocks for IP
221 IpSessionCleanup);
222 }
223
224 #ifdef ENABLE_HA
225 ha_set_api(IPPROTO_IP, &ha_ip_api);
226 #endif
227 }
228
229 void StreamResetIp (void)
230 {
231 session_api->purge_session_cache(ip_lws_cache);
232 }
233
234 void StreamCleanIp (void)
235 {
236 if ( ip_lws_cache )
237 s5stats.ip_prunes = session_api->get_session_prune_count( SESSION_PROTO_IP );
238
239 /* Clean up hash table -- delete all sessions */
240 session_api->delete_session_cache( SESSION_PROTO_IP );
241 ip_lws_cache = NULL;
242 }
243
244 //-------------------------------------------------------------------------
245 // public config methods
246 //-------------------------------------------------------------------------
247
248 void StreamIpPolicyInit (StreamIpConfig* config, char* args)
249 {
250 if (config == NULL)
251 return;
252
253 StreamParseIpArgs(args, &config->default_policy);
254 StreamPrintIpConfig(&config->default_policy);
255 }
256
257 void StreamIpConfigFree (StreamIpConfig* config)
258 {
259 if (config == NULL)
260 return;
261
262 free(config);
263 }
264
265 int StreamVerifyIpConfig (StreamIpConfig* config, tSfPolicyId policy_id)
266 {
267 if (config == NULL)
268 return -1;
269
270 if (!ip_lws_cache)
271 return -1;
272
273 return 0;
274 }
275
276 //-------------------------------------------------------------------------
277 // public access methods
278 //-------------------------------------------------------------------------
279
280 uint32_t StreamGetIpPrunes (void)
281 {
282 if( ip_lws_cache )
283 return session_api->get_session_prune_count( SESSION_PROTO_IP );
284 else
285 return s5stats.ip_prunes;
286 }
287
288 void StreamResetIpPrunes (void)
289 {
290 session_api->reset_session_prune_count( SESSION_PROTO_IP );
291 }
292
293 //-------------------------------------------------------------------------
294 // private packet processing methods
295 //-------------------------------------------------------------------------
296
297 static inline void InitSession (Packet* p, SessionControlBlock *scb)
298 {
299 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
300 "Stream IP session initialized!\n"););
301
302 s5stats.total_ip_sessions++;
303 s5stats.active_ip_sessions++;
304 IP_COPY_VALUE(scb->client_ip, GET_SRC_IP(p));
305 IP_COPY_VALUE(scb->server_ip, GET_DST_IP(p));
306 }
307
308 static inline int BlockedSession (Packet* p, SessionControlBlock *scb)
309 {
310 if ( !(scb->ha_state.session_flags & (SSNFLAG_DROP_CLIENT|SSNFLAG_DROP_SERVER)) )
311 return 0;
312
313 if (
314 ((p->packet_flags & PKT_FROM_SERVER) && (scb->ha_state.session_flags & SSNFLAG_DROP_SERVER)) ||
315 ((p->packet_flags & PKT_FROM_CLIENT) && (scb->ha_state.session_flags & SSNFLAG_DROP_CLIENT)) )
316 {
317 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
318 "Blocking %s packet as session was blocked\n",
319 p->packet_flags & PKT_FROM_SERVER ? "server" : "client"););
320
321 DisableDetect( p );
322 if ( scb->ha_state.session_flags & SSNFLAG_FORCE_BLOCK )
323 Active_ForceDropSessionWithoutReset();
324 else
325 Active_DropSessionWithoutReset(p);
326
327 #ifdef ACTIVE_RESPONSE
328 StreamActiveResponse(p, scb);
329 #endif
330 if (pkt_trace_enabled)
331 addPktTraceData(VERDICT_REASON_STREAM, snprintf(trace_line, MAX_TRACE_LINE,
332 "Stream: session was already blocked, %s\n", getPktTraceActMsg()));
333 else addPktTraceData(VERDICT_REASON_STREAM, 0);
334 return 1;
335 }
336 return 0;
337 }
338
339 static inline int IgnoreSession (Packet* p, SessionControlBlock *scb)
340 {
341 if (
342 ((p->packet_flags & PKT_FROM_SERVER) && (scb->ha_state.ignore_direction & SSN_DIR_FROM_CLIENT)) ||
343 ((p->packet_flags & PKT_FROM_CLIENT) && (scb->ha_state.ignore_direction & SSN_DIR_FROM_SERVER)) )
344 {
345 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
346 "Stream Ignoring packet from %d. Session marked as ignore\n",
347 p->packet_flags & PKT_FROM_CLIENT? "sender" : "responder"););
348
349 session_api->disable_inspection(scb, p);
350 return 1;
351 }
352
353 return 0;
354 }
355
356 #ifdef ENABLE_EXPECTED_IP
357 static inline int CheckExpectedSession (Packet* p, SessionControlBlock *scb)
358 {
359 int ignore;
360
361 ignore = StreamExpectCheck(p, scb);
362
363 if (ignore)
364 {
365 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
366 "Stream: Ignoring packet from %d. Marking session marked as ignore.\n",
367 p->packet_flags & PKT_FROM_CLIENT? "sender" : "responder"););
368
369 scb->ha_state.ignore_direction = ignore;
370 session_api->disable_inspection(scb, p);
371 return 1;
372 }
373
374 return 0;
375 }
376 #endif
377
378 static inline void UpdateSession (Packet* p, SessionControlBlock* scb)
379 {
380 MarkupPacketFlags(p, scb);
381
382 if ( !(scb->ha_state.session_flags & SSNFLAG_ESTABLISHED) )
383 {
384
385 if ( p->packet_flags & PKT_FROM_CLIENT )
386 {
387 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
388 "Stream: Updating on packet from client\n"););
389
390 scb->ha_state.session_flags |= SSNFLAG_SEEN_CLIENT;
391 }
392 else
393 {
394 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
395 "Stream: Updating on packet from server\n"););
396
397 scb->ha_state.session_flags |= SSNFLAG_SEEN_SERVER;
398 }
399
400 if ( (scb->ha_state.session_flags & SSNFLAG_SEEN_CLIENT) &&
401 (scb->ha_state.session_flags & SSNFLAG_SEEN_SERVER) )
402 {
403 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
404 "Stream: session established!\n"););
405
406 scb->ha_state.session_flags |= SSNFLAG_ESTABLISHED;
407
408 #ifdef ACTIVE_RESPONSE
409 SetTTL(scb, p, 0);
410 #endif
411 }
412 }
413
414 // Reset the session timeout.
415 {
416 StreamIpPolicy* policy;
417 policy = (StreamIpPolicy*)scb->proto_policy;
418
419 session_api->set_expire_timer(p, scb, policy->session_timeout);
420 }
421 }
422
423 //-------------------------------------------------------------------------
424 // public packet processing method
425 //-------------------------------------------------------------------------
426
427 int StreamProcessIp( Packet *p, SessionControlBlock *scb, SessionKey *skey )
428 {
429 PROFILE_VARS;
430
431 PREPROC_PROFILE_START( s5IpPerfStats );
432
433 if( scb->proto_policy == NULL )
434 {
435 scb->proto_policy = ( ( StreamConfig * ) scb->stream_config )->ip_config;
436 #if defined(DAQ_CAPA_CST_TIMEOUT)
437 if (Daq_Capa_Timeout)
438 {
439 StreamIpPolicy* policy;
440 uint64_t timeout;
441 policy = (StreamIpPolicy*)scb->proto_policy;
442 GetTimeout(p,&timeout);
443 policy->session_timeout = timeout;
444 }
445 #endif
446 }
447 if( !scb->session_established )
448 {
449 scb->session_established = true;
450 InitSession(p, scb);
451
452 #ifdef ENABLE_EXPECTED_IP
453 if( CheckExpectedSession( p, scb ) )
454 {
455 PREPROC_PROFILE_END( s5IpPerfStats );
456 return 0;
457 }
458 #endif
459 }
460 else
461 {
462 if( ( scb->session_state & STREAM_STATE_TIMEDOUT ) || StreamExpire( p, scb ) )
463 {
464 scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
465
466 /* Session is timed out */
467 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Stream IP session timeout!\n"););
468
469 #ifdef ENABLE_HA
470 /* Notify the HA peer of the session cleanup/reset by way of a deletion notification. */
471 PREPROC_PROFILE_TMPEND( s5IpPerfStats );
472 SessionHANotifyDeletion( scb );
473 scb->ha_flags = ( HA_FLAG_NEW | HA_FLAG_MODIFIED | HA_FLAG_MAJOR_CHANGE );
474 PREPROC_PROFILE_TMPSTART( s5IpPerfStats );
475 #endif
476
477 /* Clean it up */
478 IpSessionCleanup( scb );
479
480 #ifdef ENABLE_EXPECTED_IP
481 if( CheckExpectedSession( p, scb ) )
482 {
483 PREPROC_PROFILE_END( s5IpPerfStats );
484 return 0;
485 }
486 #endif
487 }
488 }
489
490 session_api->set_packet_direction_flag( p, scb );
491 p->ssnptr = scb;
492
493 if( BlockedSession( p, scb ) || IgnoreSession( p, scb ) )
494 {
495 PREPROC_PROFILE_END( s5IpPerfStats );
496 return 0;
497 }
498
499 UpdateSession( p, scb );
500
501 PREPROC_PROFILE_END( s5IpPerfStats );
502
503 return 0;
504 }
505
506 #ifdef SNORT_RELOAD
507 void SessionIPReload(uint32_t max_sessions, uint16_t pruningTimeout, uint16_t nominalTimeout)
508 {
509 SessionReload(ip_lws_cache, max_sessions, pruningTimeout, nominalTimeout
510 #ifdef REG_TEST
511 , "IP"
512 #endif
513 );
514 }
515
516 unsigned SessionIPReloadAdjust(unsigned maxWork)
517 {
518 return SessionProtocolReloadAdjust(ip_lws_cache, session_configuration->max_ip_sessions,
519 maxWork, 0
520 #ifdef REG_TEST
521 , "IP"
522 #endif
523 );
524 }
525 #endif
526
527 size_t get_ip_used_mempool()
528 {
529 if (ip_lws_cache && ip_lws_cache->protocol_session_pool)
530 return ip_lws_cache->protocol_session_pool->used_memory;
531
532 return 0;
533 }