"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 }