"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/dynamic-preprocessors/s7commplus/s7comm_roptions.c" (16 Oct 2020, 8022 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 "s7comm_roptions.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * This program is free software; you can redistribute it and/or modify
    3  * it under the terms of the GNU General Public License Version 2 as
    4  * published by the Free Software Foundation.  You may not use, modify or
    5  * distribute this program under any other version of the GNU General
    6  * Public License.
    7  *
    8  * This program is distributed in the hope that it will be useful,
    9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11  * GNU General Public License for more details.
   12  *
   13  * You should have received a copy of the GNU General Public License
   14  * along with this program; if not, write to the Free Software
   15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   16  *
   17  * Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved.
   18  *
   19  * Authors: Jeffrey Gu <jgu@cisco.com>, Pradeep Damodharan <prdamodh@cisco.com>
   20  *
   21  * Rule options for S7commplus preprocessor
   22  *
   23  */
   24 
   25 #include <string.h>
   26 
   27 #include "sf_types.h"
   28 #include "sf_snort_plugin_api.h"
   29 #include "sf_dynamic_preprocessor.h"
   30 #include "spp_s7comm.h"
   31 #include "s7comm_decode.h"
   32 #include "s7comm_roptions.h"
   33 #include "s7comm_paf.h"
   34 
   35 static s7commplus_opcode_map_t s7commplus_opcode_map[] =
   36 {
   37     {"request",      0x31},
   38     {"response",     0x32},
   39     {"notification", 0x33},
   40     {"response2",    0x02}
   41 };
   42 
   43 /* Mapping of name -> function code for 's7commplus_function' option. */
   44 static s7commplus_func_map_t s7commplus_func_map[] =
   45 {
   46     {"explore",          0x04BB},
   47     {"createobject",     0x04CA},
   48     {"deleteobject",     0x04D4},
   49     {"setvariable",      0x04F2},
   50     {"getlink",          0x0524},
   51     {"setmultivar",      0x0542},
   52     {"getmultivar",      0x054C},
   53     {"beginsequence",    0x0556},
   54     {"endsequence",      0x0560},
   55     {"invoke",           0x056B},
   56     {"getvarsubstr",     0x0586}
   57 };
   58 
   59 int S7commplusOpcodeInit(struct _SnortConfig *sc, char *name, char *params, void **data)
   60 {
   61     char *endptr;
   62     s7commplus_option_data_t *s7commplus_data;
   63     unsigned int opcode = 0;
   64 
   65     if (name == NULL || data == NULL)
   66         return 0;
   67 
   68     if (strcmp(name, S7COMMPLUS_OPCODE_NAME) != 0)
   69         return 0;
   70 
   71     if (params == NULL)
   72     {
   73         DynamicPreprocessorFatalMessage("%s(%d): No argument given for s7commplus_opcode. "
   74                 "s7commplus_opcode requires a number between 0 and 0xFF.\n",
   75                 *_dpd.config_file, *_dpd.config_line);
   76     }
   77 
   78     s7commplus_data = (s7commplus_option_data_t *)calloc(1, sizeof(s7commplus_option_data_t));
   79     if (s7commplus_data == NULL)
   80     {
   81         DynamicPreprocessorFatalMessage("%s(%d) Failed to allocate memory for "
   82                 "s7commplus_option_data_t data structure.\n", __FILE__, __LINE__);
   83     }
   84 
   85     /* Parsing time */
   86     if (isdigit(params[0]))
   87     {
   88         /* argument given as integer (hexidecimal) */
   89         opcode = _dpd.SnortStrtoul(params, &endptr, 16);
   90         if ((opcode > 255) || (*endptr != '\0'))
   91         {
   92             DynamicPreprocessorFatalMessage("%s(%d): s7commplus_opcode requires a "
   93                     "number between 0 and 0xFF.\n", *_dpd.config_file, *_dpd.config_line);
   94         }
   95     } else {
   96         /* Check the argument against the map */
   97         size_t i;
   98         int parse_success = 0;
   99         for (i = 0; i < (sizeof(s7commplus_opcode_map) / sizeof(s7commplus_opcode_map_t)); i++)
  100         {
  101             if (strcmp(params, s7commplus_opcode_map[i].name) == 0)
  102             {
  103                 parse_success = 1;
  104                 opcode = s7commplus_opcode_map[i].opcode;
  105                 break;
  106             }
  107         }
  108 
  109         if (!parse_success)
  110         {
  111             DynamicPreprocessorFatalMessage("%s(%d): s7commplus_opcode requires a "
  112                     "number between 0 and 0xFF, or a valid opcode name.\n",
  113                     *_dpd.config_file, *_dpd.config_line);
  114         }
  115     }
  116 
  117     s7commplus_data->type = S7COMMPLUS_OPCODE;
  118     s7commplus_data->arg = (uint8_t) opcode;
  119 
  120     *data = (void *)s7commplus_data;
  121 
  122     return 1;
  123 }
  124 
  125 int S7commplusFuncInit(struct _SnortConfig *sc, char *name, char *params, void **data)
  126 {
  127     char *endptr;
  128     s7commplus_option_data_t *s7commplus_data;
  129     unsigned int func = 0;
  130 
  131     if (name == NULL || data == NULL)
  132         return 0;
  133 
  134     if (strcmp(name, S7COMMPLUS_FUNC_NAME) != 0)
  135         return 0;
  136 
  137     if (params == NULL)
  138     {
  139         DynamicPreprocessorFatalMessage("%s(%d): No argument given for s7commplus_function. "
  140                 "s7commplus_function requires a number between 0 and 0xFFFF.\n",
  141                 *_dpd.config_file, *_dpd.config_line);
  142     }
  143 
  144     s7commplus_data = (s7commplus_option_data_t *)calloc(1, sizeof(s7commplus_option_data_t));
  145     if (s7commplus_data == NULL)
  146     {
  147         DynamicPreprocessorFatalMessage("%s(%d) Failed to allocate memory for "
  148                 "s7commplus_option_data_t data structure.\n", __FILE__, __LINE__);
  149     }
  150 
  151     /* Parsing time */
  152     if (isdigit(params[0]))
  153     {
  154         /* argument given as integer (hexidecimal) */
  155         func = _dpd.SnortStrtoul(params, &endptr, 16);
  156         if ((func > 0xFFFF) || (*endptr != '\0'))
  157         {
  158             DynamicPreprocessorFatalMessage("%s(%d): s7commplus_function requires a "
  159                     "number between 0 and 0xFFFF.\n", *_dpd.config_file, *_dpd.config_line);
  160         }
  161     } else {
  162         /* Check the argument against the map */
  163         size_t i;
  164         int parse_success = 0;
  165         for (i = 0; i < (sizeof(s7commplus_func_map) / sizeof(s7commplus_func_map_t)); i++)
  166         {
  167             if (strcmp(params, s7commplus_func_map[i].name) == 0)
  168             {
  169                 parse_success = 1;
  170                 func = s7commplus_func_map[i].func;
  171                 break;
  172             }
  173         }
  174 
  175         if (!parse_success)
  176         {
  177             DynamicPreprocessorFatalMessage("%s(%d): s7commplus_function requires a "
  178                     "number between 0 and 0xFFFF, or a valid function name.\n",
  179                     *_dpd.config_file, *_dpd.config_line);
  180         }
  181     }
  182 
  183     s7commplus_data->type = S7COMMPLUS_FUNC;
  184     s7commplus_data->arg = (uint16_t) func;
  185 
  186     *data = (void *)s7commplus_data;
  187 
  188     return 1;    
  189 }
  190 
  191 int S7commplusContentInit(struct _SnortConfig *sc, char *name, char *params, void **data)
  192 {
  193     s7commplus_option_data_t *s7commplus_data;
  194 
  195     if (strcmp(name, S7COMMPLUS_CONTENT_NAME) != 0)
  196         return 0;
  197 
  198     /* Nothing to parse. */
  199     if (params)
  200     {
  201         DynamicPreprocessorFatalMessage("%s(%d): s7commplus_content does not take "
  202                 "any arguments.\n", *_dpd.config_file, *_dpd.config_line);
  203     }
  204 
  205     s7commplus_data = (s7commplus_option_data_t *)calloc(1, sizeof(s7commplus_option_data_t));
  206     if (s7commplus_data == NULL)
  207     {
  208         DynamicPreprocessorFatalMessage("%s(%d) Failed to allocate memory for "
  209                 "s7commplus_option_data_t data structure.\n", __FILE__, __LINE__);
  210     }
  211 
  212     s7commplus_data->type = S7COMMPLUS_CONTENT;
  213     s7commplus_data->arg = 0;
  214 
  215     *data = (void *)s7commplus_data;
  216     return 1;
  217 }
  218 
  219 /* S7commplus rule evaluation callback. */
  220 int S7commplusRuleEval(void *raw_packet, const uint8_t **cursor, void *data)
  221 {
  222     SFSnortPacket *packet = (SFSnortPacket *)raw_packet;
  223     s7commplus_option_data_t *rule_data = (s7commplus_option_data_t *)data;
  224     s7commplus_session_data_t *session_data;
  225 
  226     /*
  227      * The preprocessor only evaluates PAF-flushed PDUs. If the rule options
  228      * don't check for this, they'll fire on stale session data when the
  229      * original packet goes through before flushing.
  230      */
  231     if (!PacketHasFullPDU(packet) && S7commplusIsPafActive(packet))
  232         return RULE_NOMATCH;
  233 
  234     session_data = (s7commplus_session_data_t *)
  235         _dpd.sessionAPI->get_application_data(packet->stream_session, PP_S7COMMPLUS);
  236 
  237     if ((packet->payload_size == 0 ) || (session_data == NULL))
  238     {
  239         return RULE_NOMATCH;
  240     }
  241 
  242     switch (rule_data->type)
  243     {
  244         case S7COMMPLUS_OPCODE:
  245             if (session_data->s7commplus_proto_id != S7COMMPLUS_PROTOCOL_ID)
  246                 return RULE_NOMATCH;
  247             if (session_data->s7commplus_opcode == rule_data->arg)
  248                 return RULE_MATCH;
  249             break;
  250 
  251         case S7COMMPLUS_FUNC:
  252             if (session_data->s7commplus_proto_id != S7COMMPLUS_PROTOCOL_ID)
  253                 return RULE_NOMATCH;
  254             if (session_data->s7commplus_function == rule_data->arg)
  255                 return RULE_MATCH;
  256             break;
  257 
  258         case S7COMMPLUS_CONTENT:
  259             if (session_data->s7commplus_proto_id != S7COMMPLUS_PROTOCOL_ID)
  260                 return RULE_NOMATCH;
  261             if (packet->payload_size < TPKT_MIN_HDR_LEN + S7COMMPLUS_MIN_HDR_LEN)
  262                 return RULE_NOMATCH;
  263 
  264             /* S7commplus data */
  265             *cursor = (const uint8_t *) (packet->payload + TPKT_MIN_HDR_LEN + S7COMMPLUS_MIN_HDR_LEN);
  266             _dpd.SetAltDetect((uint8_t *)*cursor, (uint16_t)(packet->payload_size - TPKT_MIN_HDR_LEN - S7COMMPLUS_MIN_HDR_LEN));
  267 
  268             return RULE_MATCH;
  269     }
  270 
  271     return RULE_NOMATCH;
  272 }