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