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