"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/dynamic-preprocessors/ftptelnet/spp_ftptelnet.c" (16 Oct 2020, 24360 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_ftptelnet.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  * spp_ftptelnet.c
    3  *
    4  * Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    5  * Copyright (C) 2004-2013 Sourcefire, Inc.
    6  * Steven A. Sturges <ssturges@sourcefire.com>
    7  * Daniel J. Roelker <droelker@sourcefire.com>
    8  * Marc A. Norton <mnorton@sourcefire.com>
    9  * Kevin Liu <kliu@sourcefire.com>
   10  *
   11  * This program is free software; you can redistribute it and/or modify
   12  * it under the terms of the GNU General Public License Version 2 as
   13  * published by the Free Software Foundation.  You may not use, modify or
   14  * distribute this program under any other version of the GNU General
   15  * Public License.
   16  *
   17  * This program is distributed in the hope that it will be useful,
   18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20  * GNU General Public License for more details.
   21  *
   22  * You should have received a copy of the GNU General Public License
   23  * along with this program; if not, write to the Free Software
   24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   25  *
   26  * Description:
   27  *
   28  * This file initializes FTPTelnet as a Snort preprocessor.
   29  *
   30  * This file registers the FTPTelnet initialization function,
   31  * adds the FTPTelnet function into the preprocessor list, reads
   32  * the user configuration in the snort.conf file, and prints out
   33  * the configuration that is read.
   34  *
   35  * In general, this file is a wrapper to FTPTelnet functionality,
   36  * by interfacing with the Snort preprocessor functions.  The rest
   37  * of FTPTelnet should be separate from the preprocessor hooks.
   38  *
   39  * NOTES:
   40  * - 16.09.04:  Initial Development.  SAS
   41  *
   42  */
   43 
   44 #include <assert.h>
   45 #include <string.h>
   46 #include <stdio.h>
   47 #include <sys/types.h>
   48 
   49 #ifdef HAVE_CONFIG_H
   50 #include "config.h"
   51 #endif
   52 
   53 #include "sf_types.h"
   54 #include "snort_debug.h"
   55 
   56 #include "ftpp_ui_config.h"
   57 #include "snort_ftptelnet.h"
   58 #include "spp_ftptelnet.h"
   59 #include "sf_preproc_info.h"
   60 
   61 #include "profiler.h"
   62 
   63 #include "sfPolicy.h"
   64 #include "sfPolicyUserData.h"
   65 #ifdef REG_TEST
   66 #include "ftpp_si.h"
   67 #endif
   68 
   69 #ifdef DUMP_BUFFER
   70 #include "ftptelnet_buffer_dump.h"
   71 #endif
   72 
   73 #include "reg_test.h"
   74 
   75 const int MAJOR_VERSION = 1;
   76 const int MINOR_VERSION = 2;
   77 const int BUILD_VERSION = 13;
   78 const char *PREPROC_NAME = "SF_FTPTELNET";
   79 
   80 #define SetupFTPTelnet DYNAMIC_PREPROC_SETUP
   81 
   82 
   83 /*
   84  * Defines for preprocessor initialization
   85  */
   86 /*
   87  * snort.conf preprocessor keyword
   88  */
   89 #define GLOBAL_KEYWORD   "ftp_telnet"
   90 #define PROTOCOL_KEYWORD "ftp_telnet_protocol"
   91 
   92 /*
   93  * The length of the error string buffer.
   94  */
   95 #define ERRSTRLEN 1000
   96 
   97 /*
   98  * External Global Variables
   99  * Variables that we need from Snort to log errors correctly and such.
  100  */
  101 #ifdef PERF_PROFILING
  102 PreprocStats ftpPerfStats;
  103 PreprocStats telnetPerfStats;
  104 #ifdef TARGET_BASED
  105 PreprocStats ftpdataPerfStats;
  106 #endif
  107 #endif
  108 FTPTelnet_Stats ftp_telnet_stats;
  109 
  110 /*
  111  * Global Variables
  112  * This is the only way to work with Snort preprocessors because
  113  * the user configuration must be kept between the Init function
  114  * the actual preprocessor.  There is no interaction between the
  115  * two except through global variable usage.
  116  */
  117 tSfPolicyUserContextId ftp_telnet_config = NULL;
  118 FTPTELNET_GLOBAL_CONF *ftp_telnet_eval_config = NULL;
  119 
  120 #ifdef TARGET_BASED
  121 int16_t ftp_app_id = 0;
  122 int16_t ftp_data_app_id = 0;
  123 int16_t telnet_app_id = 0;
  124 #endif
  125 
  126 /* static function prototypes */
  127 static void FTPTelnetReset(int, void *);
  128 static void FTPTelnetResetStats(int, void *);
  129 static void FTPTelnetStats(int);
  130 
  131 #ifdef SNORT_RELOAD
  132 static void FtpTelnetReloadGlobal(struct _SnortConfig *, char *, void **);
  133 static void FtpTelnetReload(struct _SnortConfig *, char *, void **);
  134 static int FtpTelnetReloadVerify(struct _SnortConfig *, void *);
  135 static void * FtpTelnetReloadSwap(struct _SnortConfig *, void *);
  136 static void FtpTelnetReloadSwapFree(void *);
  137 #endif
  138 
  139 extern char *maxToken;
  140 
  141 /*
  142  * Function: FTPTelnetChecks(Packet *p)
  143  *
  144  * Purpose: This function wraps the functionality in the generic FTPTelnet
  145  *          processing.  We get a Packet structure and pass this into the
  146  *          FTPTelnet module where the first stage in FTPTelnet is the
  147  *          Normalization stage where most of the other Snortisms are
  148  *          taken care of.  After that, the modules are generic.
  149  *
  150  * Arguments: p         => pointer to a Packet structure that contains
  151  *                         Snort info about the packet.
  152  *
  153  * Returns: None
  154  *
  155  */
  156 void FTPTelnetChecks(void *pkt, void *context)
  157 {
  158     SFSnortPacket *p = (SFSnortPacket*)pkt;
  159 
  160     // precondition - what we registered for
  161     assert(IsTCP(p) && p->payload && p->payload_size);
  162 
  163     SnortFTPTelnet(p);
  164 }
  165 
  166 #ifdef TARGET_BASED
  167 void FTPDataTelnetChecks(void *pkt, void *context)
  168 {
  169     SFSnortPacket *p = (SFSnortPacket*)pkt;
  170 
  171     // precondition - what we registered for
  172     assert(IsTCP(p));
  173 
  174     if ( _dpd.fileAPI->get_max_file_depth(NULL, false) >= 0 )
  175     {
  176         if ( _dpd.sessionAPI->get_application_protocol_id(p->stream_session)
  177             == ftp_data_app_id )
  178         {
  179             PROFILE_VARS;
  180             PREPROC_PROFILE_START(ftpdataPerfStats);
  181             SnortFTPData(p);
  182             PREPROC_PROFILE_END(ftpdataPerfStats);
  183             return;
  184         }
  185     }
  186     if ( !p->payload_size || (p->payload == NULL) )
  187         return;
  188 
  189     SnortFTPTelnet(p);
  190 }
  191 #endif
  192 
  193 /*
  194  * Function: FTPTelnetInit(char *args)
  195  *
  196  * Purpose: This function cleans up FTPTelnet memory from the configuration
  197  *          data.
  198  *
  199  * Arguments: sig       => signal causing this to be called
  200  *            args      => pointer to a context strucutre
  201  *
  202  * Returns: None
  203  *
  204  */
  205 void FTPTelnetCleanExit(int sig, void *args)
  206 {
  207     FTPTelnetFreeConfigs(ftp_telnet_config);
  208     ftp_telnet_config = NULL;
  209 }
  210 
  211 /*
  212  * Function: FTPTelnetInit(char *args)
  213  *
  214  * Purpose: This function initializes FTPTelnetInit with a user configuration.
  215  *          The function is called when FTPTelnet is configured in snort.conf.
  216  *          It gets passed a string of arguments, which gets parsed into
  217  *          configuration constructs that FTPTelnet understands.
  218  *
  219  *          This function gets called for every FTPTelnet configure line.  We
  220  *          use this characteristic to split up the configuration, so each
  221  *          line is a configuration construct.  We need to keep track of what
  222  *          part of the configuration has been configured, so we don't
  223  *          configure one part, then configure it again.
  224  *
  225  *          Any upfront memory is allocated here (if necessary).
  226  *
  227  * Arguments: args      => pointer to a string to the preprocessor arguments.
  228  *
  229  * Returns: None
  230  *
  231  */
  232 
  233 extern char* mystrtok (char* s, const char* delim);
  234 
  235 #ifdef REG_TEST
  236 static inline void PrintFTPSize(void)
  237 {
  238     _dpd.logMsg("\nFTP Session Size: %lu\n", (long unsigned int)sizeof(FTP_SESSION));
  239 }
  240 #endif
  241 
  242 static void FTPTelnetInit(struct _SnortConfig *sc, char *args)
  243 {
  244     char  *pcToken;
  245     char ErrorString[ERRSTRLEN];
  246     int iErrStrLen = ERRSTRLEN;
  247     int iRet = 0;
  248     tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
  249     FTPTELNET_GLOBAL_CONF *pPolicyConfig = NULL;
  250 
  251     ErrorString[0] = '\0';
  252 
  253 #ifdef REG_TEST
  254     PrintFTPSize();
  255 #endif
  256 
  257     if ((args == NULL) || (strlen(args) == 0))
  258     {
  259         DynamicPreprocessorFatalMessage("%s(%d) No arguments to FtpTelnet "
  260                 "configuration.\n", *_dpd.config_file, *_dpd.config_line);
  261     }
  262 
  263     /* Find out what is getting configured */
  264     maxToken = args + strlen(args);
  265     pcToken = mystrtok(args, CONF_SEPARATORS);
  266     if (pcToken == NULL)
  267     {
  268         DynamicPreprocessorFatalMessage("%s(%d)mystrtok returned NULL when it "
  269                                         "should not.", __FILE__, __LINE__);
  270     }
  271 
  272     if (ftp_telnet_config == NULL)
  273     {
  274         //create a context
  275         ftp_telnet_config = sfPolicyConfigCreate();
  276 
  277         if (ftp_telnet_config == NULL)
  278         {
  279             DynamicPreprocessorFatalMessage("No memory to allocate "
  280                                             "FTP/Telnet configuration.\n");
  281         }
  282 
  283         _dpd.addPreprocExit(FTPTelnetCleanExit, NULL, PRIORITY_APPLICATION, PP_FTPTELNET);
  284         _dpd.addPreprocReset(FTPTelnetReset, NULL, PRIORITY_APPLICATION, PP_FTPTELNET);
  285         _dpd.addPreprocResetStats(FTPTelnetResetStats, NULL, PRIORITY_APPLICATION, PP_FTPTELNET);
  286         _dpd.addPreprocConfCheck(sc, FTPConfigCheck);
  287         _dpd.registerPreprocStats("ftp_telnet", FTPTelnetStats);
  288 
  289 #ifdef PERF_PROFILING
  290         _dpd.addPreprocProfileFunc("ftptelnet_ftp", (void*)&ftpPerfStats, 0, _dpd.totalPerfStats, NULL);
  291         _dpd.addPreprocProfileFunc("ftptelnet_telnet", (void*)&telnetPerfStats, 0, _dpd.totalPerfStats, NULL);
  292 #ifdef TARGET_BASED
  293         _dpd.addPreprocProfileFunc("ftptelnet_ftpdata", (void*)&ftpdataPerfStats, 0, _dpd.totalPerfStats, NULL);
  294 #endif
  295 #endif
  296 
  297 #ifdef TARGET_BASED
  298         if (_dpd.streamAPI != NULL)
  299         {
  300             /* Find and store the application ID for FTP & Telnet */
  301             ftp_app_id = _dpd.addProtocolReference("ftp");
  302             ftp_data_app_id = _dpd.addProtocolReference("ftp-data");
  303             telnet_app_id = _dpd.addProtocolReference("telnet");
  304         }
  305 
  306         // register with session to handle applications
  307         _dpd.sessionAPI->register_service_handler( PP_FTPTELNET, ftp_app_id );
  308         _dpd.sessionAPI->register_service_handler( PP_FTPTELNET, ftp_data_app_id );
  309         _dpd.sessionAPI->register_service_handler( PP_FTPTELNET, telnet_app_id );
  310 #endif
  311     }
  312 
  313     /*
  314      * Global Configuration Processing
  315      * We only process the global configuration once, but always check for
  316      * user mistakes, like configuring more than once.  That's why we
  317      * still check for the global token even if it's been checked.
  318      */
  319     sfPolicyUserPolicySet (ftp_telnet_config, policy_id);
  320     pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)sfPolicyUserDataGetCurrent(ftp_telnet_config);
  321     if (pPolicyConfig == NULL)
  322     {
  323         if (strcasecmp(pcToken, GLOBAL) != 0)
  324         {
  325             DynamicPreprocessorFatalMessage("%s(%d) Must configure the "
  326                 "ftptelnet global configuration first.\n",
  327                 *_dpd.config_file, *_dpd.config_line);
  328         }
  329 
  330         pPolicyConfig =
  331             (FTPTELNET_GLOBAL_CONF *)calloc(1, sizeof(FTPTELNET_GLOBAL_CONF));
  332 
  333         if (pPolicyConfig == NULL)
  334         {
  335             DynamicPreprocessorFatalMessage("No memory to allocate "
  336                                             "FTP/Telnet configuration.\n");
  337         }
  338 
  339         sfPolicyUserDataSetCurrent(ftp_telnet_config, pPolicyConfig);
  340 
  341         iRet = FtpTelnetInitGlobalConfig(pPolicyConfig,
  342                                          ErrorString, iErrStrLen);
  343 
  344         if (iRet == 0)
  345         {
  346             iRet = ProcessFTPGlobalConf(pPolicyConfig,
  347                                      ErrorString, iErrStrLen);
  348 
  349             if (iRet == 0)
  350             {
  351                 PrintFTPGlobalConf(pPolicyConfig);
  352 
  353                 _dpd.preprocOptRegister(sc, "ftp.bounce", &FTPPBounceInit, &FTPPBounceEval,
  354                         NULL, NULL, NULL, NULL, NULL);
  355 
  356 #ifdef TARGET_BASED
  357                 if (_dpd.streamAPI != NULL)
  358                 {
  359                     _dpd.streamAPI->set_service_filter_status
  360                         (sc, ftp_app_id, PORT_MONITOR_SESSION, policy_id, 1);
  361 
  362                     _dpd.streamAPI->set_service_filter_status
  363                         (sc, telnet_app_id, PORT_MONITOR_SESSION, policy_id, 1);
  364                 }
  365 #endif
  366             }
  367         }
  368     }
  369     else if (strcasecmp(pcToken, TELNET) == 0)
  370     {
  371         iRet = ProcessTelnetConf(pPolicyConfig, ErrorString, iErrStrLen);
  372         enableFtpTelnetPortStreamServices( sc, &pPolicyConfig->telnet_config->proto_ports, NULL,
  373                                            SSN_DIR_FROM_SERVER | SSN_DIR_FROM_CLIENT ); 
  374     }
  375     else if (strcasecmp(pcToken, FTP) == 0)
  376     {
  377         pcToken = NextToken(CONF_SEPARATORS);
  378 
  379         if ( !pcToken )
  380         {
  381             DynamicPreprocessorFatalMessage(
  382                 "%s(%d) Missing ftp_telnet ftp keyword.\n",
  383                 *(_dpd.config_file), *(_dpd.config_line));
  384         }
  385         else if (strcasecmp(pcToken, SERVER) == 0)
  386         {
  387             iRet = ProcessFTPServerConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
  388         }
  389         else if (strcasecmp(pcToken, CLIENT) == 0)
  390         {
  391             iRet = ProcessFTPClientConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
  392         }
  393         else
  394         {
  395             DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet ftp keyword.\n",
  396                                             *(_dpd.config_file), *(_dpd.config_line));
  397         }
  398     }
  399     else
  400     {
  401         DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet keyword.\n",
  402                                         *(_dpd.config_file), *(_dpd.config_line));
  403     }
  404 
  405     if (iRet)
  406     {
  407         if(iRet > 0)
  408         {
  409             /*
  410              * Non-fatal Error
  411              */
  412             if(*ErrorString)
  413             {
  414                 _dpd.errMsg("WARNING: %s(%d) => %s\n",
  415                             *(_dpd.config_file), *(_dpd.config_line), ErrorString);
  416             }
  417         }
  418         else
  419         {
  420             /*
  421              * Fatal Error, log error and exit.
  422              */
  423             if(*ErrorString)
  424             {
  425                 DynamicPreprocessorFatalMessage("%s(%d) => %s\n",
  426                                                 *(_dpd.config_file), *(_dpd.config_line), ErrorString);
  427             }
  428             else
  429             {
  430                 /*
  431                  * Check if ErrorString is undefined.
  432                  */
  433                 if(iRet == -2)
  434                 {
  435                     DynamicPreprocessorFatalMessage("%s(%d) => ErrorString is undefined.\n",
  436                                                     *(_dpd.config_file), *(_dpd.config_line));
  437                 }
  438                 else
  439                 {
  440                     DynamicPreprocessorFatalMessage("%s(%d) => Undefined Error.\n",
  441                                                     *(_dpd.config_file), *(_dpd.config_line));
  442                 }
  443             }
  444         }
  445     }
  446 }
  447 
  448 /*
  449  * Function: SetupFTPTelnet()
  450  *
  451  * Purpose: This function initializes FTPTelnet as a Snort preprocessor.
  452  *
  453  *          It registers the preprocessor keyword for use in the snort.conf
  454  *          and sets up the initialization module for the preprocessor, in
  455  *          case it is configured.
  456  *
  457  *          This function must be called in InitPreprocessors() in plugbase.c
  458  *          in order to be recognized by Snort.
  459  *
  460  * Arguments: None
  461  *
  462  * Returns: None
  463  *
  464  */
  465 void SetupFTPTelnet(void)
  466 {
  467 #ifndef SNORT_RELOAD
  468     _dpd.registerPreproc(GLOBAL_KEYWORD, FTPTelnetInit);
  469     _dpd.registerPreproc(PROTOCOL_KEYWORD, FTPTelnetInit);
  470 #else
  471     _dpd.registerPreproc(GLOBAL_KEYWORD, FTPTelnetInit, FtpTelnetReloadGlobal,
  472                          FtpTelnetReloadVerify, FtpTelnetReloadSwap,
  473                          FtpTelnetReloadSwapFree);
  474     _dpd.registerPreproc(PROTOCOL_KEYWORD, FTPTelnetInit,
  475                          FtpTelnetReload, NULL, NULL, NULL);
  476 #endif
  477 
  478     DEBUG_WRAP(DebugMessage(DEBUG_FTPTELNET, "Preprocessor: FTPTelnet is "
  479                 "setup . . .\n"););
  480 #ifdef DUMP_BUFFER
  481     _dpd.registerBufferTracer(getFTPTelnetBuffers, FTPTELNET_BUFFER_DUMP_FUNC);
  482 #endif
  483 }
  484 
  485 static void FTPTelnetReset(int signal, void *data)
  486 {
  487     return;
  488 }
  489 
  490 static void FTPTelnetResetStats(int signal, void *data)
  491 {
  492     return;
  493 }
  494 
  495 static void FTPTelnetStats(int exiting)
  496 {
  497     _dpd.logMsg("FTPTelnet Preprocessor Statistics\n");
  498     _dpd.logMsg("  Current active FTP sessions                   : " STDu64 "\n",
  499                 ftp_telnet_stats.ftp_sessions);
  500     _dpd.logMsg("  Max concurrent FTP sessions                   : " STDu64 "\n",
  501                 ftp_telnet_stats.max_ftp_sessions);
  502     _dpd.logMsg("  Total FTP Data sessions                       : " STDu64 "\n",
  503                 ftp_telnet_stats.ftp_data_sessions);
  504     _dpd.logMsg("  Max concurrent FTP Data sessions              : " STDu64 "\n",
  505                 ftp_telnet_stats.max_ftp_data_sessions);
  506     _dpd.logMsg("  Current active Telnet sessions                : " STDu64 "\n",
  507                 ftp_telnet_stats.telnet_sessions);
  508     _dpd.logMsg("  Max concurrent Telnet sessions                : " STDu64 "\n",
  509                 ftp_telnet_stats.max_telnet_sessions);
  510     _dpd.logMsg("  Current ftp_telnet session non-mempool memory : " STDu64 "\n",
  511                 ftp_telnet_stats.heap_memory);
  512 }
  513 
  514 #ifdef SNORT_RELOAD
  515 static void _FtpTelnetReload(struct _SnortConfig *sc, tSfPolicyUserContextId ftp_telnet_swap_config, char *args)
  516 {
  517     char  *pcToken;
  518     char ErrorString[ERRSTRLEN];
  519     int iErrStrLen = ERRSTRLEN;
  520     int iRet = 0;
  521     tSfPolicyId policy_id = _dpd.getParserPolicy(sc);
  522     FTPTELNET_GLOBAL_CONF *pPolicyConfig = NULL;
  523 
  524     ErrorString[0] = '\0';
  525 
  526     if ((args == NULL) || (strlen(args) == 0))
  527     {
  528         DynamicPreprocessorFatalMessage("%s(%d) No arguments to FtpTelnet "
  529                 "configuration.\n", *_dpd.config_file, *_dpd.config_line);
  530     }
  531 
  532     /* Find out what is getting configured */
  533     maxToken = args + strlen(args);
  534     pcToken = mystrtok(args, CONF_SEPARATORS);
  535     if (pcToken == NULL)
  536     {
  537         DynamicPreprocessorFatalMessage("%s(%d)mystrtok returned NULL when it "
  538                                         "should not.", __FILE__, __LINE__);
  539     }
  540 
  541     /*
  542      * Global Configuration Processing
  543      * We only process the global configuration once, but always check for
  544      * user mistakes, like configuring more than once.  That's why we
  545      * still check for the global token even if it's been checked.
  546      */
  547     sfPolicyUserPolicySet (ftp_telnet_swap_config, policy_id);
  548     pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)sfPolicyUserDataGetCurrent(ftp_telnet_swap_config);
  549 
  550     if (pPolicyConfig == NULL)
  551     {
  552         if (strcasecmp(pcToken, GLOBAL) != 0)
  553         {
  554             DynamicPreprocessorFatalMessage("%s(%d) Must configure the "
  555                 "ftptelnet global configuration first.\n",
  556                 *_dpd.config_file, *_dpd.config_line);
  557         }
  558 
  559         pPolicyConfig =
  560             (FTPTELNET_GLOBAL_CONF *)calloc(1, sizeof(FTPTELNET_GLOBAL_CONF));
  561 
  562         if (pPolicyConfig == NULL)
  563         {
  564             DynamicPreprocessorFatalMessage("No memory to allocate "
  565                                             "FTP/Telnet configuration.\n");
  566         }
  567 
  568         sfPolicyUserDataSetCurrent(ftp_telnet_swap_config, pPolicyConfig);
  569 
  570         iRet = FtpTelnetInitGlobalConfig(pPolicyConfig,
  571                                          ErrorString, iErrStrLen);
  572 
  573         if (iRet == 0)
  574         {
  575             iRet = ProcessFTPGlobalConf(pPolicyConfig,
  576                                      ErrorString, iErrStrLen);
  577 
  578             if (iRet == 0)
  579             {
  580                 PrintFTPGlobalConf(pPolicyConfig);
  581 
  582                 _dpd.preprocOptRegister(sc, "ftp.bounce", &FTPPBounceInit, &FTPPBounceEval,
  583                         NULL, NULL, NULL, NULL, NULL);
  584             }
  585         }
  586     }
  587     else if (strcasecmp(pcToken, TELNET) == 0)
  588     {
  589         iRet = ProcessTelnetConf(pPolicyConfig, ErrorString, iErrStrLen);
  590         enableFtpTelnetPortStreamServices( sc, &pPolicyConfig->telnet_config->proto_ports, NULL,
  591                                            SSN_DIR_FROM_SERVER | SSN_DIR_FROM_CLIENT ); 
  592     }
  593     else if (strcasecmp(pcToken, FTP) == 0)
  594     {
  595         pcToken = NextToken(CONF_SEPARATORS);
  596 
  597         if ( !pcToken )
  598         {
  599             DynamicPreprocessorFatalMessage(
  600                 "%s(%d) Missing ftp_telnet ftp keyword.\n",
  601                 *(_dpd.config_file), *(_dpd.config_line));
  602         }
  603         else if (strcasecmp(pcToken, SERVER) == 0)
  604         {
  605             iRet = ProcessFTPServerConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
  606         }
  607         else if (strcasecmp(pcToken, CLIENT) == 0)
  608         {
  609             iRet = ProcessFTPClientConf(sc, pPolicyConfig, ErrorString, iErrStrLen);
  610         }
  611         else
  612         {
  613             DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet ftp keyword.\n",
  614                                             *(_dpd.config_file), *(_dpd.config_line));
  615         }
  616     }
  617     else
  618     {
  619         DynamicPreprocessorFatalMessage("%s(%d) Invalid ftp_telnet keyword.\n",
  620                                         *(_dpd.config_file), *(_dpd.config_line));
  621     }
  622 
  623     if (iRet)
  624     {
  625         if(iRet > 0)
  626         {
  627             /*
  628              * Non-fatal Error
  629              */
  630             if(*ErrorString)
  631             {
  632                 _dpd.errMsg("WARNING: %s(%d) => %s\n",
  633                             *(_dpd.config_file), *(_dpd.config_line), ErrorString);
  634             }
  635         }
  636         else
  637         {
  638             /*
  639              * Fatal Error, log error and exit.
  640              */
  641             if(*ErrorString)
  642             {
  643                 DynamicPreprocessorFatalMessage("%s(%d) => %s\n",
  644                                                 *(_dpd.config_file), *(_dpd.config_line), ErrorString);
  645             }
  646             else
  647             {
  648                 /*
  649                  * Check if ErrorString is undefined.
  650                  */
  651                 if(iRet == -2)
  652                 {
  653                     DynamicPreprocessorFatalMessage("%s(%d) => ErrorString is undefined.\n",
  654                                                     *(_dpd.config_file), *(_dpd.config_line));
  655                 }
  656                 else
  657                 {
  658                     DynamicPreprocessorFatalMessage("%s(%d) => Undefined Error.\n",
  659                                                     *(_dpd.config_file), *(_dpd.config_line));
  660                 }
  661             }
  662         }
  663     }
  664 }
  665 
  666 static void FtpTelnetReloadGlobal(struct _SnortConfig *sc, char *args, void **new_config)
  667 {
  668     tSfPolicyUserContextId ftp_telnet_swap_config = (tSfPolicyUserContextId)*new_config;
  669 
  670     if (ftp_telnet_swap_config == NULL)
  671     {
  672         //create a context
  673         ftp_telnet_swap_config = sfPolicyConfigCreate();
  674 
  675         if (ftp_telnet_swap_config == NULL)
  676         {
  677             DynamicPreprocessorFatalMessage("No memory to allocate "
  678                                             "FTP/Telnet swap_configuration.\n");
  679         }
  680         *new_config = (void *)ftp_telnet_swap_config;
  681     }
  682     _FtpTelnetReload(sc, ftp_telnet_swap_config, args);
  683 }
  684 
  685 static void FtpTelnetReload(struct _SnortConfig *sc, char *args, void **new_config)
  686 {
  687     tSfPolicyUserContextId ftp_telnet_swap_config;
  688     ftp_telnet_swap_config = (tSfPolicyUserContextId)_dpd.getRelatedReloadData(sc, GLOBAL_KEYWORD);
  689     _FtpTelnetReload(sc, ftp_telnet_swap_config, args);
  690 }
  691 
  692 static int FtpTelnetReloadVerifyPolicy(
  693         struct _SnortConfig *sc,
  694         tSfPolicyUserContextId config,
  695         tSfPolicyId policyId,
  696         void* pData
  697         )
  698 {
  699     return FTPTelnetCheckConfigs( sc, pData, policyId );
  700 }
  701 
  702 static int FtpTelnetReloadVerify(struct _SnortConfig *sc, void *new_config)
  703 {
  704     tSfPolicyUserContextId ftp_telnet_swap_config = (tSfPolicyUserContextId)new_config;
  705 
  706     if (ftp_telnet_swap_config == NULL)
  707         return 0;
  708 
  709     if (sfPolicyUserDataIterate (sc, ftp_telnet_swap_config, FtpTelnetReloadVerifyPolicy))
  710         return -1;
  711 
  712     return 0;
  713 }
  714 
  715 static int FtpTelnetReloadSwapPolicy(
  716         struct _SnortConfig *sc,
  717         tSfPolicyUserContextId config,
  718         tSfPolicyId policyId,
  719         void* pData
  720         )
  721 {
  722     FTPTELNET_GLOBAL_CONF *pPolicyConfig = (FTPTELNET_GLOBAL_CONF *)pData;
  723 
  724     //do any housekeeping before freeing FTPTELNET_GLOBAL_CONF
  725     if (pPolicyConfig->ref_count == 0)
  726     {
  727         sfPolicyUserDataClear (config, policyId);
  728         FTPTelnetFreeConfig(pPolicyConfig);
  729     }
  730 
  731     return 0;
  732 }
  733 
  734 static void * FtpTelnetReloadSwap(struct _SnortConfig *sc, void *new_config)
  735 {
  736     tSfPolicyUserContextId ftp_telnet_swap_config = (tSfPolicyUserContextId)new_config;
  737     tSfPolicyUserContextId old_config = ftp_telnet_config;
  738 
  739     if (ftp_telnet_swap_config == NULL)
  740         return NULL;
  741 
  742     ftp_telnet_config = ftp_telnet_swap_config;
  743 
  744     sfPolicyUserDataIterate (sc, old_config, FtpTelnetReloadSwapPolicy);
  745 
  746     if (sfPolicyUserPolicyGetActive(old_config) == 0)
  747         return (void *)old_config;
  748 
  749     return NULL;
  750 }
  751 
  752 static void FtpTelnetReloadSwapFree(void *data)
  753 {
  754     if (data == NULL)
  755         return;
  756 
  757     FTPTelnetFreeConfigs((tSfPolicyUserContextId)data);
  758 }
  759 
  760 #endif