"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/dynamic-preprocessors/appid/spp_appid.c" (16 Oct 2020, 16406 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 "spp_appid.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 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    3 ** Copyright (C) 2005-2013 Sourcefire, Inc.
    4 **
    5 ** This program is free software; you can redistribute it and/or modify
    6 ** it under the terms of the GNU General Public License Version 2 as
    7 ** published by the Free Software Foundation.  You may not use, modify or
    8 ** distribute this program under any other version of the GNU General
    9 ** Public License.
   10 **
   11 ** This program is distributed in the hope that it will be useful,
   12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 ** GNU General Public License for more details.
   15 **
   16 ** You should have received a copy of the GNU General Public License
   17 ** along with this program; if not, write to the Free Software
   18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   19 */
   20 
   21 #include <stdint.h>
   22 #include <stdbool.h>
   23 #include <strings.h>
   24 #include <stdio.h>
   25 #include <syslog.h>
   26 #include <string.h>
   27 #include <stdlib.h>
   28 #include <ctype.h>
   29 #include <inttypes.h>
   30 #include <sys/time.h>
   31 #include <pthread.h>
   32 
   33 #include "sf_snort_packet.h"
   34 #include "sf_dynamic_preprocessor.h"
   35 #include "common_util.h"
   36 #include "sf_preproc_info.h"
   37 
   38 #include "spp_appid.h"
   39 #include "fw_appid.h"
   40 #include "flow.h"
   41 #include "service_base.h"
   42 #include "luaDetectorModule.h"
   43 #include "appIdConfig.h"
   44 #include "appIdStats.h"
   45 #ifdef SIDE_CHANNEL
   46 #include "appId_ss.h"
   47 #endif
   48 #include "appInfoTable.h"
   49 #include "thirdparty_appid_utils.h"
   50 
   51 #include "cip_common.h"
   52 #include "detector_cip.h"
   53 
   54 #ifdef PERF_PROFILING
   55 PreprocStats appMatchPerfStats;
   56 #endif
   57 
   58 const int MAJOR_VERSION = 1;
   59 const int MINOR_VERSION = 1;
   60 const int BUILD_VERSION = 5;
   61 
   62 static uint16_t appid_preproc_status_bit = 0;
   63 
   64 
   65 SF_SO_PUBLIC const char *PREPROC_NAME = "appid";
   66 
   67 static pthread_mutex_t appIdReloadMutex = PTHREAD_MUTEX_INITIALIZER;
   68 static bool appIdReloadInProgress = false;
   69 
   70 extern void appIdApiInit(struct AppIdApi*);
   71 
   72 static void AppIdProcess(SFSnortPacket *p, void *context)
   73 {
   74     PROFILE_VARS;
   75     PREPROC_PROFILE_START(appMatchPerfStats);
   76     /* Trust */
   77     if (p->stream_session && _dpd.sessionAPI->get_ignore_direction(p->stream_session) == SSN_DIR_BOTH)
   78     {
   79         _dpd.sessionAPI->disable_preproc_for_session( p->stream_session, PP_NETWORK_DISCOVERY );
   80         PREPROC_PROFILE_END(appMatchPerfStats);
   81         return;
   82     }
   83     fwAppIdSearch(p);
   84     PREPROC_PROFILE_END(appMatchPerfStats);
   85 }
   86 
   87 static void AppIdAddPortsToStream5Filter(struct _SnortConfig *sc, tSfPolicyId policy_id)
   88 {
   89     unsigned portNum;
   90 
   91     for (portNum = 0; portNum < 65536; portNum++)
   92     {
   93         /*Add port the port */
   94         _dpd.streamAPI->set_port_filter_status(sc, IPPROTO_TCP, (uint16_t)portNum,
   95                                                appid_preproc_status_bit, policy_id, 1);
   96         _dpd.streamAPI->set_port_filter_status(sc, IPPROTO_UDP, (uint16_t)portNum,
   97                                                appid_preproc_status_bit, policy_id, 1);
   98     }
   99 }
  100 
  101 static void initializeAppIDForDispatch(struct _SnortConfig *sc)
  102 {
  103     _dpd.sessionAPI->enable_preproc_all_ports_all_policies(sc, PP_APP_ID, PROTO_BIT__IP);
  104     _dpd.addPreprocAllPolicies(sc, (void (*)(void *, void *))AppIdProcess, PRIORITY_TRANSPORT + 1,
  105                                PP_APP_ID, PROTO_BIT__IP);
  106 }
  107 
  108 static int AppIDCheckConfig(struct _SnortConfig *sc)
  109 {
  110     initializeAppIDForDispatch(sc);
  111     return 0;
  112 }
  113 
  114 static void AppIdStaticConfigFree(tAppidStaticConfig* appidSC)
  115 {
  116     if (appidSC)
  117     {
  118         free((char *)(appidSC->appid_thirdparty_dir));
  119         free(appidSC->tp_config_path);
  120         free(appidSC->app_id_detector_path);
  121         free(appidSC->conf_file);
  122         free(appidSC->app_stats_filename);
  123 #ifdef SIDE_CHANNEL
  124         if (appidSC->appId_ss_config)
  125             AppIdSSConfigFree(appidSC->appId_ss_config);
  126 #endif
  127         if (appidSC->newAppIdConfig)
  128             AppIdCommonUnload(appidSC->newAppIdConfig);
  129 
  130         free(appidSC);
  131     }
  132 }
  133 
  134 #ifdef SNORT_RELOAD
  135 
  136 /********** AppId Reload Functions **********/
  137 
  138 static void reloadWait(void)
  139 {
  140     const struct timespec reloadPollTime = {0, 1000000};    // 1 msec wait time to poll reload status
  141 
  142     for (;;)
  143     {
  144         pthread_mutex_lock(&appIdReloadMutex);
  145         if (!appIdReloadInProgress)
  146         {
  147             appIdReloadInProgress = true;
  148             pthread_mutex_unlock(&appIdReloadMutex);
  149             return;
  150         }
  151         pthread_mutex_unlock(&appIdReloadMutex);
  152         nanosleep(&reloadPollTime, NULL);
  153     }
  154 }
  155 
  156 
  157 static void reloadUnlock(void)
  158 {
  159     pthread_mutex_lock(&appIdReloadMutex);
  160     appIdReloadInProgress = false;
  161     pthread_mutex_unlock(&appIdReloadMutex);
  162 }
  163 
  164 STATIC bool AppIdReloadAdjust(bool idle, tSfPolicyId raPolicyId, void* userData)
  165 {
  166     return AppIdServiceStateReloadAdjust(idle, appidStaticConfig->memcap);
  167 }
  168 
  169 static int AppIdReloadReloadVerify(struct _SnortConfig *sc, void *swap_config)
  170 {
  171     initializeAppIDForDispatch(sc);
  172     if (swap_config)
  173     {
  174         tAppidStaticConfig* newConfig = (tAppidStaticConfig*)swap_config;
  175         if (newConfig->memcap != appidStaticConfig->memcap)
  176         {
  177             _dpd.logMsg("AppId: old memcap %lu, new memcap %lu\n", appidStaticConfig->memcap, newConfig->memcap);
  178             _dpd.reloadAdjustRegister(sc, "AppID", 0, AppIdReloadAdjust, NULL, NULL);
  179         }
  180     }
  181     return 0;
  182 }
  183 
  184 /**
  185  * \brief Callback function that handles AppId reload
  186  *
  187  * This function gets called on Snort reload in a separate thread. It starts
  188  * loading AppId configuration in new_config.
  189  *
  190  * @param sc
  191  * @param args
  192  * @param new_config return parameter to hold AppId configuration
  193  * @return void
  194  */
  195 STATIC void AppIdReload(struct _SnortConfig *sc, char *args, void **new_config)
  196 {
  197     tSfPolicyId policy_id;
  198 
  199     reloadWait();
  200 
  201     policy_id = _dpd.getParserPolicy(sc);
  202 
  203     if (policy_id == _dpd.getDefaultPolicy())
  204         AppIdAddPortsToStream5Filter(sc, policy_id);
  205 
  206     if (*new_config == NULL)
  207     {
  208         tAppidStaticConfig* newConfig;
  209         if (NULL == (newConfig = (tAppidStaticConfig*)malloc(sizeof(*newConfig))))
  210         {
  211             _dpd.fatalMsg("AppID failed to allocate memory for new configuration\n");
  212         }
  213         appIdConfigParse(newConfig, args);
  214         // Start loading AppId configuration into new_config
  215         AppIdCommonReload(newConfig, (void**)&newConfig->newAppIdConfig);
  216         *new_config = (void*)newConfig;
  217     }
  218 }
  219 
  220 /**
  221  * \brief Callback function that handles configuration swap on reload
  222  *
  223  * This function gets called after AppIdReload() returns. At this point,
  224  * AppIdReload() is done with loading the configuration into swap_config
  225  * and swap_config is ready to use.
  226  *
  227  * @param sc
  228  * @param swap_config pointer to data structure containing new configuration.
  229  *        This data structure was populated by AppIdReload().
  230  * @return pointer to old configuration
  231  */
  232 STATIC void *AppIdReloadSwap(struct _SnortConfig *sc, void *swap_config)
  233 {
  234     struct timeval  startTime;
  235     struct timeval  endTime;
  236     double          elapsedTime;
  237     tAppidStaticConfig* tmpConfig = NULL;
  238 
  239     if (swap_config)
  240     {
  241         gettimeofday(&startTime, NULL);
  242 
  243         tmpConfig = appidStaticConfig;
  244         appidStaticConfig = (tAppidStaticConfig*)swap_config;
  245 
  246         tmpConfig->newAppIdConfig = AppIdCommonReloadSwap(appidStaticConfig->newAppIdConfig);
  247         appidStaticConfig->newAppIdConfig = NULL;
  248         ThirdPartyAppIDReconfigure();
  249 
  250         gettimeofday(&endTime, NULL);
  251         elapsedTime = (endTime.tv_sec*1000.0) + (endTime.tv_usec/1000.0) - (startTime.tv_sec*1000.0) - (startTime.tv_usec/1000.0);
  252 
  253         _dpd.logMsg("AppId reload swap time = %.3f msec\n", elapsedTime);
  254     }
  255 
  256     // Return old configuration data structure
  257     return (void*)tmpConfig;
  258 }
  259 
  260 /**
  261  * \brief Callback function that handles freeing of old configuration after
  262  *        configuration is swapped on a reload
  263  *
  264  * This function gets called after AppIdReloadSwap() is done. It frees the data
  265  * structure that contains the old configuration.
  266  *
  267  * @param old_context pointer to old configuration
  268  * @return void
  269  */
  270 STATIC void AppIdReloadFree(void *old_context)
  271 {
  272     AppIdStaticConfigFree((tAppidStaticConfig*)old_context);
  273     reloadUnlock();
  274 }
  275 
  276 #endif // SNORT_RELOAD
  277 
  278 /******** AppId Reconfigure Functions ********/
  279 
  280 /**
  281  * \brief Callback function that handles AppId reconfiguration
  282  *
  283  * This function gets called on AppId reconfiguration in a separate thread. It
  284  * starts loading AppId configuration into new_context.
  285  *
  286  * @param type
  287  * @param data
  288  * @param length
  289  * @param new_context return parameter to hold AppId configuration
  290  * @param statusBuf
  291  * @param statusBuf_Len
  292  * @return 0 on success
  293  */
  294 STATIC int AppIdReconfigure(uint16_t type, const uint8_t *data, uint32_t length, void **new_context,
  295                             char* statusBuf, int statusBuf_len)
  296 {
  297     reloadWait();
  298 
  299     if (*new_context == NULL)
  300     {
  301         AppIdCommonReload(appidStaticConfig, new_context);
  302     }
  303 
  304     return 0;
  305 }
  306 
  307 /**
  308  * \brief Callback function that handles AppId reconfiguration swap
  309  *
  310  * This function gets called adter AppIdReconfigure() returns. At this point,
  311  * AppIdReconfigure() is done with loading the configuration into new_context
  312  * and new_context is ready to use.
  313  *
  314  * @param type
  315  * @param new_context pointer to data structure that contains AppId's new
  316  *        configuration. This data structure was populated by AppIdReconfigure().
  317  * @param old_context return parameter that points to old configuration
  318  * @return 0 on success
  319  */
  320 STATIC int AppIdReconfigureSwap(uint16_t type, void *new_context, void **old_context)
  321 {
  322     struct timeval  startTime;
  323     struct timeval  endTime;
  324     double          elapsedTime;
  325 
  326     gettimeofday(&startTime, NULL);
  327 
  328     if (new_context)
  329     {
  330         if (*old_context == NULL)
  331         {
  332             // Return current configuration in old_context
  333             *old_context = AppIdCommonReloadSwap(new_context);
  334             ThirdPartyAppIDReconfigure();
  335         }
  336     }
  337 
  338     _dpd.logMsg("AppId", "Reconfigured");
  339 
  340     gettimeofday(&endTime, NULL);
  341     elapsedTime = (endTime.tv_sec*1000.0) + (endTime.tv_usec/1000.0) - (startTime.tv_sec*1000.0) - (startTime.tv_usec/1000.0);
  342 
  343     _dpd.logMsg("AppId reconfigure swap time = %.3f msec\n", elapsedTime);
  344 
  345     return 0;
  346 }
  347 
  348 /**
  349  * \brief Callback function that handles freeing of old AppId configuration
  350  *
  351  * This function gets called after AppIdReconfigureSwap() returns. It frees the
  352  * data strcuture that contains the old configuration.
  353  *
  354  * @param type
  355  * @param old_context pointer to data structure that contains AppId's old
  356  *        configuration. This pointer was returned by AppIdReconfigureSwap().
  357  * @param te
  358  * @param f
  359  * @return void
  360  */
  361 STATIC void AppIdReconfigureFree(uint16_t type, void *old_context, struct _THREAD_ELEMENT *te, ControlDataSendFunc f)
  362 {
  363     if (old_context)
  364     {
  365         AppIdCommonUnload(old_context);
  366     }
  367 
  368     reloadUnlock();
  369 }
  370 
  371 void AppIdDumpStats(int exit_flag)
  372 {
  373     _dpd.logMsg("Application Identification Preprocessor:\n");
  374     _dpd.logMsg("   Total packets received : %lu\n", app_id_raw_packet_count);
  375     _dpd.logMsg("  Total packets processed : %lu\n", app_id_processed_packet_count);
  376     _dpd.logMsg("    Total packets ignored : %lu\n", app_id_ignored_packet_count);
  377     _dpd.logMsg("    Total ongoing AppId sessions : %lu\n", app_id_ongoing_session);
  378     _dpd.logMsg("    Total AppId sessions allocated : %lu\n", app_id_total_alloc);
  379     _dpd.logMsg("    AppId session size : %lu\n", sizeof(tAppIdData));
  380     if (exit_flag == 0)    // Snort's SigDumpStatsHandler dumping stats intentionally
  381     {
  382         if (thirdparty_appid_module)
  383             thirdparty_appid_module->print_stats();
  384         AppIdServiceStateDumpStats();
  385         RNAPndDumpLuaStats();
  386 #ifdef SIDE_CHANNEL
  387         AppIdPrintSSStats();
  388 #endif
  389     }
  390 }
  391 
  392 static void appIdIdleProcessing(void)
  393 {
  394     appIdStatsIdleFlush();
  395 }
  396 
  397 static void AppIdResetStats(int signal, void *data)
  398 {
  399     app_id_raw_packet_count = 0;
  400     app_id_processed_packet_count = 0;
  401     app_id_ignored_packet_count = 0;
  402     app_id_ongoing_session = 0;
  403     app_id_total_alloc = 0;
  404     if (thirdparty_appid_module)
  405         thirdparty_appid_module->reset_stats();
  406 #ifdef SIDE_CHANNEL
  407     AppIdResetSSStats();
  408 #endif
  409 }
  410 
  411 static void AppIdCleanExit(int signal, void *unused)
  412 {
  413     AppIdCommonFini();
  414 #ifdef SIDE_CHANNEL
  415     AppIdCleanSS();
  416 #endif
  417     AppIdStaticConfigFree(appidStaticConfig);
  418 }
  419 
  420 static int ThirdPartyReload(uint16_t type, void *new_context, void **old_context)
  421 {
  422     if (thirdparty_appid_module != NULL)
  423     {
  424         thirdparty_appid_module->print_stats();
  425     }
  426     ThirdPartyAppIDFini();
  427     ThirdPartyAppIDInit(appidStaticConfig);
  428     return 0;
  429 }
  430 
  431 static void AppIdInit(struct _SnortConfig *sc, char *args)
  432 {
  433     static int once = 0;
  434     tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
  435 
  436     if (!once)
  437     {
  438         _dpd.addPreprocExit(AppIdCleanExit, NULL, PRIORITY_LAST, PP_APP_ID);
  439 #       ifdef PERF_PROFILING
  440         _dpd.addPreprocProfileFunc("fwApp", &appMatchPerfStats, 0, _dpd.totalPerfStats, NULL);
  441         _dpd.addPreprocProfileFunc("fwAppTP", &tpPerfStats, 1, &appMatchPerfStats, NULL);
  442         _dpd.addPreprocProfileFunc("fwLibAppTP", &tpLibPerfStats, 2, &tpPerfStats, NULL);
  443         _dpd.addPreprocProfileFunc("fwHTTP", &httpPerfStats, 2, &tpPerfStats, NULL);
  444         _dpd.addPreprocProfileFunc("fwClientPat", &clientMatchPerfStats, 1, &appMatchPerfStats, NULL);
  445         _dpd.addPreprocProfileFunc("fwServicePat", &serviceMatchPerfStats, 1, &appMatchPerfStats, NULL);
  446         _dpd.addPreprocProfileFunc("luaDetectors", &luaDetectorsPerfStats, 1, &appMatchPerfStats, NULL);
  447         _dpd.addPreprocProfileFunc("cisco", &luaCiscoPerfStats, 2, &luaDetectorsPerfStats, NULL);
  448         _dpd.addPreprocProfileFunc("custom", &luaCustomPerfStats, 2, &luaDetectorsPerfStats, NULL);
  449 #       endif
  450         appid_preproc_status_bit = _dpd.sessionAPI->get_preprocessor_status_bit();
  451 
  452         if (NULL == (appidStaticConfig = (tAppidStaticConfig*)malloc(sizeof(*appidStaticConfig))))
  453         {
  454             _dpd.fatalMsg("AppID failed to allocate memory for the configuration\n"); 
  455         }
  456         appIdConfigParse(appidStaticConfig, args);
  457 
  458         AppIdCommonInit(appidStaticConfig);
  459         ThirdPartyAppIDInit(appidStaticConfig);
  460         if (appidStaticConfig->app_id_dump_ports)
  461         {
  462             dumpPorts(stdout, pAppidActiveConfig);
  463             appInfoTableDump(pAppidActiveConfig);
  464             exit(0);
  465         }
  466         _dpd.addPreprocResetStats(AppIdResetStats, NULL, PRIORITY_LAST, PP_APP_ID);
  467         _dpd.registerPreprocStats(PREPROC_NAME, AppIdDumpStats);
  468         /* Hook into control socket to handle reload */
  469         _dpd.controlSocketRegisterHandler(73, AppIdReconfigure, AppIdReconfigureSwap, AppIdReconfigureFree);
  470         _dpd.controlSocketRegisterHandler(74, AppIdDebug, NULL, NULL);
  471         _dpd.controlSocketRegisterHandler(56, NULL, ThirdPartyReload, NULL);
  472 
  473         _dpd.registerIdleHandler(appIdIdleProcessing);
  474         _dpd.registerGetAppId(getOpenAppId);
  475         if (!thirdparty_appid_module)
  476             _dpd.streamAPI->register_http_header_callback(httpHeaderCallback);
  477         _dpd.registerSslAppIdLookup(sslAppGroupIdLookup);
  478         if (_dpd.streamAPI->service_event_subscribe(PP_SIP, SIP_EVENT_TYPE_SIP_DIALOG, SipSessionSnortCallback) == false)
  479             DynamicPreprocessorFatalMessage("failed to subscribe to SIP_DIALOG\n");
  480 
  481         if (_dpd.streamAPI->service_event_subscribe(PP_CIP, CIP_EVENT_TYPE_CIP_DATA, CipSessionSnortCallback) == false)
  482             DynamicPreprocessorFatalMessage("failed to subscribe to CIP_EVENT_TYPE_CIP_DATA\n");
  483         
  484         _dpd.registerSetTlsHostAppId(setTlsHost);
  485 
  486         appIdApiInit(_dpd.appIdApi);
  487 #ifdef SIDE_CHANNEL
  488         _dpd.addFuncToPostConfigList(sc, AppIdSSPostConfigInit, NULL);
  489 #endif
  490         once = 1;
  491     }
  492 
  493     _dpd.addPreprocConfCheck(sc, AppIDCheckConfig);
  494 
  495     if (policy_id == _dpd.getDefaultPolicy())
  496         AppIdAddPortsToStream5Filter(sc, policy_id);
  497 }
  498 
  499 #define SetupApplicationPreproc DYNAMIC_PREPROC_SETUP
  500 
  501 SF_SO_PUBLIC void SetupApplicationPreproc(void)
  502 {
  503 #ifndef SNORT_RELOAD
  504     _dpd.registerPreproc(PREPROC_NAME, AppIdInit);
  505 #else
  506     _dpd.registerPreproc(PREPROC_NAME, AppIdInit, AppIdReload, AppIdReloadReloadVerify, AppIdReloadSwap, AppIdReloadFree);
  507 #endif
  508 }
  509 
  510