"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/preprocessors/Stream6/stream_common.c" (16 Oct 2020, 18375 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 "stream_common.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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "sf_types.h"
28 #include "snort_debug.h"
29 #include "decode.h"
30 #include "log.h"
31 #include "util.h"
32 #include "generators.h"
33 #include "event_queue.h"
34 #include "snort.h"
35
36 #include "session_api.h"
37
38 #include "stream_common.h"
39 #include "portscan.h"
40 #include "sftarget_protocol_reference.h"
41 #include "sp_dynamic.h"
42 #include "snort_stream_tcp.h"
43 #include "snort_stream_udp.h"
44 #include "snort_stream_icmp.h"
45 #include "snort_stream_ip.h"
46 #include "parser.h"
47 #include "active.h"
48 #ifdef ENABLE_HA
49 #include "stream5_ha.h"
50 #endif
51
52 static void printIgnoredRules(
53 IgnoredRuleList *pIgnoredRuleList,
54 int any_any_flow
55 );
56 static void addRuleToIgnoreList(
57 IgnoredRuleList **ppIgnoredRuleList,
58 OptTreeNode *otn);
59
60 /* M A C R O S **************************************************/
61
62 int StreamExpireSession(SessionControlBlock *scb)
63 {
64 #ifdef ENABLE_HA
65 /* Sessions in standby cannot be locally expired. */
66 if (scb->ha_flags & HA_FLAG_STANDBY)
67 return 0;
68 #endif
69
70 sfBase.iStreamTimeouts++;
71 scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
72 scb->session_state |= STREAM_STATE_TIMEDOUT;
73
74 switch (scb->protocol)
75 {
76 case IPPROTO_TCP:
77 s5stats.tcp_timeouts++;
78 break;
79 case IPPROTO_UDP:
80 s5stats.udp_timeouts++;
81 break;
82 case IPPROTO_ICMP:
83 s5stats.icmp_timeouts++;
84 break;
85 }
86
87 return 1;
88 }
89
90 void StreamDeleteSession(SessionControlBlock *scb)
91 {
92 sfBase.iStreamTimeouts++;
93 scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
94
95 switch (scb->protocol)
96 {
97 case IPPROTO_TCP:
98 s5stats.tcp_timeouts++;
99 break;
100 case IPPROTO_UDP:
101 s5stats.udp_timeouts++;
102 break;
103 case IPPROTO_ICMP:
104 s5stats.icmp_timeouts++;
105 case IPPROTO_IP:
106 s5stats.ip_timeouts++;
107 break;
108 }
109
110 if ( session_api->delete_session_by_key(scb, "timeout") != SFXHASH_OK )
111 {
112 LogMessage("WARNING: failed to delete session. \n");
113 }
114 }
115
116 int StreamExpire(Packet *p, SessionControlBlock *scb)
117 {
118 uint64_t pkttime = CalcJiffies(p);
119
120 if (scb->expire_time == 0)
121 {
122 /* Not yet set, not expired */
123 return 0;
124 }
125
126 if((int)(pkttime - scb->expire_time) > 0)
127 {
128 /* Expiration time has passed. */
129 return StreamExpireSession(scb);
130 }
131
132 return 0;
133 }
134
135 #ifdef ACTIVE_RESPONSE
136 int StreamGetExpire(Packet *p, SessionControlBlock *scb)
137 {
138 return ( CalcJiffies(p) > scb->expire_time );
139 }
140
141 // *DROP* flags are set to mark the direction(s) for which traffic was
142 // seen since last reset and then cleared after sending new attempt so
143 // that we only send in the still active direction(s).
144 void StreamActiveResponse(Packet* p, SessionControlBlock *scb)
145 {
146 StreamConfig *config = sfPolicyUserDataGet(stream_online_config, getNapRuntimePolicy());
147 uint8_t max = config->session_config->max_active_responses;
148
149 if ( p->packet_flags & PKT_FROM_CLIENT )
150 scb->session_state |= STREAM_STATE_DROP_CLIENT;
151 else
152 scb->session_state |= STREAM_STATE_DROP_SERVER;
153
154 if ( (scb->response_count < max) && session_api->get_expire_timer(p, scb) )
155 {
156 uint32_t delay = config->session_config->min_response_seconds;
157 EncodeFlags flags =
158 ( (scb->session_state & STREAM_STATE_DROP_CLIENT) &&
159 (scb->session_state & STREAM_STATE_DROP_SERVER) ) ?
160 ENC_FLAG_FWD : 0; // reverse dir is always true
161
162 Active_KillSession(p, &flags);
163 ++scb->response_count;
164 #if defined(DAQ_CAPA_CST_TIMEOUT)
165 if (!Daq_Capa_Timeout)
166 #endif
167 session_api->set_expire_timer(p, scb, delay);
168
169 scb->session_state &= ~(STREAM_STATE_DROP_CLIENT|STREAM_STATE_DROP_SERVER);
170 }
171 }
172
173 void SetTTL (SessionControlBlock* ssn, Packet* p, int client)
174 {
175 uint8_t inner_ttl = 0, outer_ttl = 0;
176 if ( p->outer_iph_api )
177 outer_ttl = p->outer_iph_api->iph_ret_ttl(p);
178
179 if ( p->iph_api )
180 inner_ttl = p->iph_api->iph_ret_ttl(p);
181 if ( client )
182 {
183 ssn->outer_client_ttl = outer_ttl;
184 ssn->inner_client_ttl = inner_ttl;
185 }
186 else
187 {
188 ssn->outer_server_ttl = outer_ttl;
189 ssn->inner_server_ttl = inner_ttl;
190 }
191 }
192 #endif
193
194 void MarkupPacketFlags(Packet *p, SessionControlBlock *scb)
195 {
196 if(!scb)
197 return;
198
199 if((scb->ha_state.session_flags & SSNFLAG_ESTABLISHED) != SSNFLAG_ESTABLISHED)
200 {
201 if((scb->ha_state.session_flags & (SSNFLAG_SEEN_SERVER|SSNFLAG_SEEN_CLIENT)) !=
202 (SSNFLAG_SEEN_SERVER|SSNFLAG_SEEN_CLIENT))
203 {
204 p->packet_flags |= PKT_STREAM_UNEST_UNI;
205 }
206 }
207 else
208 {
209 p->packet_flags |= PKT_STREAM_EST;
210 if(p->packet_flags & PKT_STREAM_UNEST_UNI)
211 {
212 p->packet_flags ^= PKT_STREAM_UNEST_UNI;
213 }
214 }
215 }
216
217 #if 0
218 /** Get rule list for a specific protocol
219 *
220 * @param rule
221 * @param ptocool protocol type
222 * @returns RuleTreeNode* rule list for specific protocol
223 */
224 static inline RuleTreeNode * protocolRuleList(RuleListNode *rule, IpProto protocol)
225 {
226 switch (protocol)
227 {
228 case IPPROTO_TCP:
229 return rule->RuleList->TcpList;
230 case IPPROTO_UDP:
231 return rule->RuleList->UdpList;
232 case IPPROTO_ICMP:
233 break;
234 default:
235 break;
236 }
237 return NULL;
238 }
239 #endif
240 static inline char * getProtocolName (IpProto protocol)
241 {
242 static char *protocolName[] = {"TCP", "UDP", "ICMP"};
243 switch (protocol)
244 {
245 case IPPROTO_TCP:
246 return protocolName[0];
247 case IPPROTO_UDP:
248 return protocolName[1];
249 case IPPROTO_ICMP:
250 return protocolName[2];
251 break;
252 default:
253 break;
254 }
255 return NULL;
256 }
257
258 /**check whether a flow bit is set for an option node.
259 *
260 * @param otn Option Tree Node
261 * @returns 0 - no flow bit is set, 1 otherwise
262 */
263 int StreamOtnHasFlowOrFlowbit(OptTreeNode *otn)
264 {
265 if (otn->ds_list[PLUGIN_CLIENTSERVER] ||
266 DynamicHasFlow(otn) ||
267 DynamicHasFlowbit(otn) ||
268 otn->ds_list[PLUGIN_FLOWBIT])
269 {
270 return 1;
271 }
272 return 0;
273 }
274
275 /**initialize given port list from the given ruleset, for a given policy
276 * @param portList pointer to array of MAX_PORTS+1 uint8_t. This array content
277 * is changed by walking through the rulesets.
278 * @param protocol - protocol type
279 */
280 void setPortFilterList(
281 struct _SnortConfig *sc,
282 uint16_t *portList,
283 IpProto protocol,
284 int ignoreAnyAnyRules,
285 tSfPolicyId policyId
286 )
287 {
288 char *port_array = NULL;
289 int num_ports = 0;
290 int i;
291 RuleTreeNode *rtn;
292 OptTreeNode *otn;
293 int inspectSrc, inspectDst;
294 char any_any_flow = 0;
295 IgnoredRuleList *pIgnoredRuleList = NULL; ///list of ignored rules
296 char *protocolName;
297 SFGHASH_NODE *hashNode;
298 int flowBitIsSet = 0;
299
300 if (sc == NULL)
301 {
302 FatalError("%s(%d) Snort conf for parsing is NULL.\n",
303 __FILE__, __LINE__);
304 }
305
306 if (((protocol == IPPROTO_TCP) || (protocol == IPPROTO_UDP)) && (ignoreAnyAnyRules == 0))
307 {
308 int j;
309 for (j=0; j<MAX_PORTS; j++)
310 {
311 portList[j] |= PORT_MONITOR_SESSION | PORT_MONITOR_INSPECT;
312 }
313 return;
314 }
315
316 protocolName = getProtocolName(protocol);
317
318 /* Post-process TCP rules to establish TCP ports to inspect. */
319 for (hashNode = sfghash_findfirst(sc->otn_map);
320 hashNode;
321 hashNode = sfghash_findnext(sc->otn_map))
322 {
323 otn = (OptTreeNode *)hashNode->data;
324 flowBitIsSet = StreamOtnHasFlowOrFlowbit(otn);
325
326 rtn = getRtnFromOtn(otn, policyId);
327
328 if (!rtn)
329 {
330 continue;
331 }
332
333 if (rtn->proto == protocol)
334 {
335 //do operation
336 inspectSrc = inspectDst = 0;
337 if (PortObjectHasAny(rtn->src_portobject))
338 {
339 inspectSrc = -1;
340 }
341 else
342 {
343 port_array = PortObjectCharPortArray(port_array, rtn->src_portobject, &num_ports);
344 if (port_array && num_ports != 0)
345 {
346 inspectSrc = 1;
347 for (i=0;i<SFPO_MAX_PORTS;i++)
348 {
349 if (port_array[i])
350 {
351 portList[i] |= PORT_MONITOR_INSPECT;
352 /* port specific rule */
353 /* Look for an OTN with flow or flowbits keyword */
354 if (flowBitIsSet)
355 {
356 portList[i] |= PORT_MONITOR_SESSION;
357 }
358 }
359 }
360 }
361 if ( port_array )
362 {
363 free(port_array);
364 port_array = NULL;
365 }
366 }
367 if (PortObjectHasAny(rtn->dst_portobject))
368 {
369 inspectDst = -1;
370 }
371 else
372 {
373 port_array = PortObjectCharPortArray(port_array, rtn->dst_portobject, &num_ports);
374 if (port_array && num_ports != 0)
375 {
376 inspectDst = 1;
377 for (i=0;i<SFPO_MAX_PORTS;i++)
378 {
379 if (port_array[i])
380 {
381 portList[i] |= PORT_MONITOR_INSPECT;
382 /* port specific rule */
383 if (flowBitIsSet)
384 {
385 portList[i] |= PORT_MONITOR_SESSION;
386 }
387 }
388 }
389 }
390 if ( port_array )
391 {
392 free(port_array);
393 port_array = NULL;
394 }
395 }
396 if ((inspectSrc == -1) && (inspectDst == -1))
397 {
398 /* any -> any rule */
399 if (any_any_flow == 0)
400 {
401 any_any_flow = StreamAnyAnyFlow(portList, otn, rtn, any_any_flow,
402 &pIgnoredRuleList, ignoreAnyAnyRules);
403 }
404 }
405 }
406 }
407
408 /* If portscan is tracking TCP/UDP, need to create
409 * sessions for all ports */
410 if (((protocol == IPPROTO_UDP) && (ps_get_protocols(sc, policyId) & PS_PROTO_UDP))
411 || ((protocol == IPPROTO_TCP) && (ps_get_protocols(sc, policyId) & PS_PROTO_TCP)))
412 {
413 int j;
414 for (j=0; j<MAX_PORTS; j++)
415 {
416 portList[j] |= PORT_MONITOR_SESSION;
417 }
418 }
419
420 if (any_any_flow == 1)
421 {
422 LogMessage("WARNING: 'ignore_any_rules' option for Stream %s "
423 "disabled because of %s rule with flow or flowbits option.\n",
424 protocolName, protocolName);
425 }
426
427 else if (pIgnoredRuleList)
428 {
429 LogMessage("WARNING: Rules (GID:SID) effectively ignored because of "
430 "'ignore_any_rules' option for Stream %s.\n", protocolName);
431 }
432 // free list; print iff any_any_flow
433 printIgnoredRules(pIgnoredRuleList, any_any_flow);
434
435 }
436
437 /**Determines whether any_any_flow should be ignored or not.
438 *
439 * Dont ignore any_any_flows if flow bit is set on an any_any_flow,
440 * or ignoreAnyAnyRules is not set.
441 * @param portList port list
442 * @param rtn Rule tree node
443 * @param any_any_flow - set if any_any_flow is ignored,0 otherwise
444 * @param ppIgnoredRuleList
445 * @param ignoreAnyAnyRules
446 * @returns
447 */
448 int StreamAnyAnyFlow(
449 uint16_t *portList,
450 OptTreeNode *otn,
451 RuleTreeNode *rtn,
452 int any_any_flow,
453 IgnoredRuleList **ppIgnoredRuleList,
454 int ignoreAnyAnyRules
455 )
456 {
457 /**if any_any_flow is set then following code has no effect.*/
458 if (any_any_flow)
459 {
460 return any_any_flow;
461 }
462
463 /* Look for an OTN with flow or flowbits keyword */
464 if (StreamOtnHasFlowOrFlowbit(otn))
465 {
466 int i;
467
468 for (i=1;i<=MAX_PORTS;i++)
469 {
470 /* track sessions for ALL ports becuase
471 * of any -> any with flow/flowbits */
472 portList[i] |= PORT_MONITOR_SESSION;
473 }
474 return 1;
475 }
476
477 if (ignoreAnyAnyRules)
478 {
479
480 /* if not, then ignore the content/pcre/etc */
481 if (otn->ds_list[PLUGIN_PATTERN_MATCH] ||
482 otn->ds_list[PLUGIN_PATTERN_MATCH_OR] ||
483 otn->ds_list[PLUGIN_PATTERN_MATCH_URI] ||
484 DynamicHasContent(otn) ||
485 DynamicHasByteTest(otn) ||
486 DynamicHasPCRE(otn) ||
487 otn->ds_list[PLUGIN_BYTE_TEST] ||
488 otn->ds_list[PLUGIN_PCRE])
489 {
490 /* Ignoring this rule.... */
491 addRuleToIgnoreList(ppIgnoredRuleList, otn);
492 }
493 }
494
495 return 0;
496 }
497
498 /**add rule to the ignore rule list.
499 */
500 static void addRuleToIgnoreList(IgnoredRuleList **ppIgnoredRuleList, OptTreeNode *otn)
501 {
502 IgnoredRuleList *ignored_rule;
503
504 ignored_rule = SnortAlloc(sizeof(*ignored_rule));
505 ignored_rule->otn = otn;
506 ignored_rule->next = *ppIgnoredRuleList;
507 *ppIgnoredRuleList = ignored_rule;
508 }
509
510
511 /**print the ignored rule list.
512 */
513 static void printIgnoredRules(
514 IgnoredRuleList *pIgnoredRuleList,
515 int any_any_flow
516 )
517 {
518 char six_sids = 0;
519 int sids_ignored = 0;
520 char buf[STD_BUF];
521 IgnoredRuleList *ignored_rule;
522 IgnoredRuleList *next_ignored_rule;
523
524 buf[0] = '\0';
525
526 for (ignored_rule = pIgnoredRuleList; ignored_rule != NULL; )
527 {
528 if (any_any_flow == 0)
529 {
530 if (six_sids == 1)
531 {
532 SnortSnprintfAppend(buf, STD_BUF-1, "\n");
533 LogMessage("%s", buf);
534 six_sids = 0;
535 }
536
537 if (sids_ignored == 0)
538 {
539 SnortSnprintf(buf, STD_BUF-1, " %d:%d",
540 ignored_rule->otn->sigInfo.generator,
541 ignored_rule->otn->sigInfo.id);
542 }
543 else
544 {
545 SnortSnprintfAppend(buf, STD_BUF-1, ", %d:%d",
546 ignored_rule->otn->sigInfo.generator,
547 ignored_rule->otn->sigInfo.id);
548 }
549 sids_ignored++;
550 if (sids_ignored %6 == 0)
551 {
552 /* Have it print next time through */
553 six_sids = 1;
554 sids_ignored = 0;
555 }
556 }
557 next_ignored_rule = ignored_rule->next;
558 free(ignored_rule);
559 ignored_rule = next_ignored_rule;
560 }
561
562 if (sids_ignored || six_sids)
563 {
564 SnortSnprintfAppend(buf, STD_BUF-1, "\n");
565 LogMessage("%s", buf);
566 }
567 }
568
569 static int StreamFreeConfigsPolicy(
570 tSfPolicyUserContextId config,
571 tSfPolicyId policyId,
572 void* pData
573 )
574 {
575 StreamConfig *pPolicyConfig = (StreamConfig *)pData;
576
577 //do any housekeeping before freeing StreamConfig
578 sfPolicyUserDataClear (config, policyId);
579 StreamFreeConfig(pPolicyConfig);
580
581 return 0;
582 }
583
584 void StreamFreeConfigs(tSfPolicyUserContextId config)
585 {
586 if (config == NULL)
587 return;
588
589 sfPolicyUserDataFreeIterate(config, StreamFreeConfigsPolicy);
590
591 sfPolicyConfigDelete(config);
592 }
593
594 void StreamFreeConfig(StreamConfig *config)
595 {
596 if (config == NULL)
597 return;
598
599 if (config->tcp_config != NULL)
600 {
601 StreamTcpConfigFree(config->tcp_config);
602 config->tcp_config = NULL;
603 }
604
605 if (config->udp_config != NULL)
606 {
607 StreamUdpConfigFree(config->udp_config);
608 config->udp_config = NULL;
609 }
610
611 if (config->icmp_config != NULL)
612 {
613 StreamIcmpConfigFree(config->icmp_config);
614 config->icmp_config = NULL;
615 }
616
617 if (config->ip_config != NULL)
618 {
619 StreamIpConfigFree(config->ip_config);
620 config->ip_config = NULL;
621 }
622
623 free(config);
624 }
625
626 int StreamSetRuntimeConfiguration( SessionControlBlock *scb, uint8_t protocol )
627 {
628 StreamConfig *pPolicyConfig;
629
630 pPolicyConfig = ( StreamConfig * ) sfPolicyUserDataGet( stream_online_config, getNapRuntimePolicy() );
631 if (pPolicyConfig == NULL)
632 return -1;
633
634 stream_session_config = pPolicyConfig->session_config;
635
636 return 0;
637 }
638
639 bool getStreamIgnoreAnyConfig (struct _SnortConfig *sc, IpProto protocol)
640 {
641 StreamConfig *config;
642 tSfPolicyId policyId;
643
644 for (policyId = 0; policyId < sfPolicyNumAllocated(sc->policy_config); policyId++) {
645
646 if ((config = getStreamPolicyConfig(policyId, 0))) {
647 switch (protocol) {
648 case IPPROTO_TCP :
649 if ((config->tcp_config) && (config->tcp_config->default_policy->flags & STREAM_CONFIG_IGNORE_ANY))
650 return true;
651 case IPPROTO_UDP :
652 if ((config->udp_config) && (config->udp_config->default_policy->flags & STREAM_CONFIG_IGNORE_ANY))
653 return true;
654 default:
655 break;
656 }
657 }
658 }
659 return false;
660 }