"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/dynamic-preprocessors/appid/service_plugins/service_snmp.c" (16 Oct 2020, 17915 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 "service_snmp.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 
   22 #include <ctype.h>
   23 #include <string.h>
   24 #include <stdlib.h>
   25 #include <stddef.h>
   26 #include <sys/types.h>
   27 #include <netinet/in.h>
   28 
   29 #include "appIdApi.h"
   30 #include "appInfoTable.h"
   31 #include "flow.h"
   32 #include "service_api.h"
   33 
   34 #define SNMP_PORT   161
   35 
   36 #define SNMP_VERSION_1  0
   37 #define SNMP_VERSION_2c 1
   38 #define SNMP_VERSION_2u 2
   39 #define SNMP_VERSION_3  3
   40 
   41 #define SNMP_VENDOR_STR     "SNMP"
   42 #define SNMP_VERSION_STR_1  "v1"
   43 #define SNMP_VERSION_STR_2c "v2c"
   44 #define SNMP_VERSION_STR_2u "v2u"
   45 #define SNMP_VERSION_STR_3  "v3"
   46 
   47 typedef enum
   48 {
   49     SNMP_STATE_CONNECTION,
   50     SNMP_STATE_RESPONSE,
   51     SNMP_STATE_REQUEST,
   52     SNMP_STATE_R_RESPONSE,
   53     SNMP_STATE_R_REQUEST,
   54     SNMP_STATE_ERROR
   55 } SNMPState;
   56 
   57 typedef struct _SERVICE_SNMP_DATA
   58 {
   59     SNMPState state;
   60 } ServiceSNMPData;
   61 
   62 typedef enum
   63 {
   64     SNMP_PDU_GET_REQUEST,
   65     SNMP_PDU_GET_NEXT_REQUEST,
   66     SNMP_PDU_GET_RESPONSE,
   67     SNMP_PDU_SET_REQUEST,
   68     SNMP_PDU_TRAP,
   69     SNMP_PDU_GET_BULK_REQUEST,
   70     SNMP_PDU_INFORM_REQUEST,
   71     SNMP_PDU_TRAPV2
   72 } SNMPPDUType;
   73 
   74 #pragma pack(1)
   75 
   76 typedef struct _SERVICE_SNMP_HEADER
   77 {
   78     uint16_t opcode;
   79     union
   80     {
   81         uint16_t block;
   82         uint16_t errorcode;
   83     } d;
   84 } ServiceSNMPHeader;
   85 
   86 #pragma pack()
   87 
   88 static int snmp_init(const InitServiceAPI * const init_api);
   89 static int snmp_validate(ServiceValidationArgs* args);
   90 
   91 static tRNAServiceElement svc_element =
   92 {
   93     .next = NULL,
   94     .validate = &snmp_validate,
   95     .detectorType = DETECTOR_TYPE_DECODER,
   96     .name = "snmp",
   97     .ref_count = 1,
   98     .current_ref_count = 1,
   99 };
  100 
  101 static RNAServiceValidationPort pp[] =
  102 {
  103     {&snmp_validate, SNMP_PORT, IPPROTO_TCP},
  104     {&snmp_validate, SNMP_PORT, IPPROTO_UDP},
  105     {&snmp_validate, 162, IPPROTO_UDP},
  106     {NULL, 0, 0}
  107 };
  108 
  109 tRNAServiceValidationModule snmp_service_mod =
  110 {
  111     "SNMP",
  112     &snmp_init,
  113     pp
  114 };
  115 
  116 static uint8_t SNMP_PATTERN_2[] = {0x02, 0x01, 0x00, 0x04};
  117 static uint8_t SNMP_PATTERN_3[] = {0x02, 0x01, 0x01, 0x04};
  118 static uint8_t SNMP_PATTERN_4[] = {0x02, 0x01, 0x03, 0x30};
  119 
  120 static tAppRegistryEntry appIdRegistry[] =
  121 {
  122     {APP_ID_SNMP, APPINFO_FLAG_SERVICE_UDP_REVERSED|APPINFO_FLAG_SERVICE_ADDITIONAL}
  123 };
  124 
  125 static int16_t app_id = 0;
  126 
  127 static int snmp_init(const InitServiceAPI * const init_api)
  128 {
  129 #ifdef TARGET_BASED
  130     app_id = init_api->dpd->addProtocolReference("snmp");
  131 #endif
  132 
  133     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_2, sizeof(SNMP_PATTERN_2), 2, "snmp", init_api->pAppidConfig);
  134     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_3, sizeof(SNMP_PATTERN_3), 2, "snmp", init_api->pAppidConfig);
  135     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_4, sizeof(SNMP_PATTERN_4), 2, "snmp", init_api->pAppidConfig);
  136     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_2, sizeof(SNMP_PATTERN_2), 3, "snmp", init_api->pAppidConfig);
  137     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_3, sizeof(SNMP_PATTERN_3), 3, "snmp", init_api->pAppidConfig);
  138     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_4, sizeof(SNMP_PATTERN_4), 3, "snmp", init_api->pAppidConfig);
  139     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_2, sizeof(SNMP_PATTERN_2), 4, "snmp", init_api->pAppidConfig);
  140     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_3, sizeof(SNMP_PATTERN_3), 4, "snmp", init_api->pAppidConfig);
  141     init_api->RegisterPattern(&snmp_validate, IPPROTO_UDP, SNMP_PATTERN_4, sizeof(SNMP_PATTERN_4), 4, "snmp", init_api->pAppidConfig);
  142     unsigned i;
  143     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
  144     {
  145         _dpd.debugMsg(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[i].appId);
  146         init_api->RegisterAppId(&snmp_validate, appIdRegistry[i].appId, appIdRegistry[i].additionalInfo, init_api->pAppidConfig);
  147     }
  148 
  149     return 0;
  150 }
  151 
  152 static int snmp_ans1_length(const uint8_t * * const data,
  153                             const uint8_t * const end,
  154                             uint32_t * const length)
  155 {
  156     *length = 0;
  157     if (**data == 0x80) return -1;
  158     if (**data < 0x80)
  159     {
  160         *length = (uint32_t)**data;
  161         (*data)++;
  162     }
  163     else
  164     {
  165         int cnt = (**data) & 0x7F;
  166         (*data)++;
  167         for (; *data<end && cnt; cnt--, (*data)++)
  168         {
  169             *length <<= 8;
  170             *length |= **data;
  171         }
  172         if (cnt) return -1;
  173     }
  174     return 0;
  175 }
  176 
  177 static int snmp_verify_packet(const uint8_t * * const data,
  178                               const uint8_t * const end, uint8_t * const pdu,
  179                               uint8_t * version_ret)
  180 {
  181     uint32_t overall_length;
  182     uint32_t community_length;
  183     uint32_t global_length;
  184     uint32_t length;
  185     uint8_t version;
  186     uint8_t cls;
  187     const uint8_t *p;
  188 
  189     if (**data != 0x30) return -1;
  190     (*data)++;
  191     if (*data >= end) return -1;
  192     if (snmp_ans1_length(data, end, &overall_length)) return -1;
  193     if (overall_length < 3 || (int)overall_length > end-(*data)) return -1;
  194     if (**data != 0x02) return -1;
  195     (*data)++;
  196     if (**data != 0x01) return -1;
  197     (*data)++;
  198     version = **data;
  199     (*data)++;
  200     overall_length -= 3;
  201     if (!overall_length) return -1;
  202     switch (version)
  203     {
  204     case SNMP_VERSION_1:
  205     case SNMP_VERSION_2c:
  206         if (**data != 0x04) return -1;
  207         (*data)++;
  208         overall_length--;
  209         if (!overall_length) return -1;
  210         p = *data;
  211         if (snmp_ans1_length(data, *data+overall_length, &community_length))
  212             return -1;
  213         overall_length -= *data - p;
  214         if (overall_length < community_length)
  215             return -1;
  216         for (;
  217              community_length;
  218              (*data)++, community_length--, overall_length--)
  219         {
  220             if (!isprint(**data)) return -1;
  221         }
  222         break;
  223     case SNMP_VERSION_2u:
  224         if (**data != 0x04) return -1;
  225         (*data)++;
  226         overall_length--;
  227         if (!overall_length) return -1;
  228         p = *data;
  229         if (snmp_ans1_length(data, *data+overall_length, &community_length))
  230             return -1;
  231         overall_length -= *data - p;
  232         if (!community_length || overall_length < community_length)
  233             return -1;
  234         if (**data != 1) return -1;
  235         *data += community_length;
  236         overall_length -= community_length;
  237         break;
  238     case SNMP_VERSION_3:
  239         /* Global header */
  240         if (**data != 0x30) return -1;
  241         (*data)++;
  242         overall_length--;
  243         if (!overall_length) return -1;
  244         p = *data;
  245         if (snmp_ans1_length(data, *data+overall_length, &global_length))
  246             return -1;
  247         overall_length -= *data - p;
  248         if (global_length < 2 || overall_length < global_length) return -1;
  249 
  250         /* Message id */
  251         if (**data != 0x02) return -1;
  252         (*data)++;
  253         global_length--;
  254         overall_length --;
  255         p = *data;
  256         if (snmp_ans1_length(data, *data+global_length, &length)) return -1;
  257         global_length -= *data - p;
  258         overall_length -= *data - p;
  259         if (global_length < length || length > sizeof(uint32_t)) return -1;
  260         *data += length;
  261         global_length -= length;
  262         overall_length -= length;
  263 
  264         /* Max message size */
  265         if (global_length < 2) return -1;
  266         if (**data != 0x02) return -1;
  267         (*data)++;
  268         global_length--;
  269         overall_length --;
  270         p = *data;
  271         if (snmp_ans1_length(data, *data+global_length, &length)) return -1;
  272         global_length -= *data - p;
  273         overall_length -= *data - p;
  274         if (global_length < length || length > sizeof(uint32_t)) return -1;
  275         *data += length;
  276         global_length -= length;
  277         overall_length -= length;
  278 
  279         /* Message flags */
  280         if (global_length < 2) return -1;
  281         if (**data != 0x04) return -1;
  282         (*data)++;
  283         global_length--;
  284         overall_length --;
  285         p = *data;
  286         if (snmp_ans1_length(data, *data+global_length, &length))
  287             return -1;
  288         global_length -= *data - p;
  289         overall_length -= *data - p;
  290         if (length != 1 || global_length < length) return -1;
  291         (*data)++;
  292         global_length--;
  293         overall_length--;
  294 
  295         /* Security model */
  296         if (global_length < 2) return -1;
  297         if (**data != 0x02) return -1;
  298         (*data)++;
  299         global_length--;
  300         overall_length --;
  301         p = *data;
  302         if (snmp_ans1_length(data, *data+global_length, &length))
  303             return -1;
  304         global_length -= *data - p;
  305         overall_length -= *data - p;
  306         if (global_length < length || length > sizeof(uint32_t)) return -1;
  307         *data += length;
  308         global_length -= length;
  309         overall_length -= length;
  310 
  311         /* Security Parameters */
  312         if (overall_length < 2) return -1;
  313         if (**data != 0x04) return -1;
  314         (*data)++;
  315         overall_length --;
  316         p = *data;
  317         if (snmp_ans1_length(data, *data+overall_length, &global_length))
  318             return -1;
  319         overall_length -= *data - p;
  320         if (overall_length < global_length) return -1;
  321         *data += global_length;
  322         overall_length -= global_length;
  323 
  324         /* Message */
  325         if (overall_length < 2) return -1;
  326         if (**data != 0x30) return -1;
  327         (*data)++;
  328         overall_length --;
  329         p = *data;
  330         if (snmp_ans1_length(data, *data+overall_length, &global_length))
  331             return -1;
  332         overall_length -= *data - p;
  333         if (overall_length < global_length) return -1;
  334 
  335         /* Context Engine ID */
  336         if (global_length < 2) return -1;
  337         if (**data != 0x04) return -1;
  338         (*data)++;
  339         global_length--;
  340         overall_length --;
  341         p = *data;
  342         if (snmp_ans1_length(data, *data+global_length, &length))
  343             return -1;
  344         global_length -= *data - p;
  345         overall_length -= *data - p;
  346         if (global_length < length) return -1;
  347         *data += length;
  348         global_length -= length;
  349         overall_length -= length;
  350 
  351         /* Context Name */
  352         if (global_length < 2) return -1;
  353         if (**data != 0x04) return -1;
  354         (*data)++;
  355         global_length--;
  356         overall_length --;
  357         p = *data;
  358         if (snmp_ans1_length(data, *data+global_length, &length))
  359             return -1;
  360         global_length -= *data - p;
  361         overall_length -= *data - p;
  362         if (global_length < length) return -1;
  363         *data += length;
  364         global_length -= length;
  365         overall_length -= length;
  366         break;
  367     default:
  368         return -1;
  369     }
  370     if (!overall_length) return -1;
  371     cls = (**data) & 0xC0;
  372     if (cls != 0x80 && cls != 0x40) return -1;
  373     *pdu = (**data) & 0x1F;
  374     *version_ret = version;
  375     return 0;
  376 }
  377 
  378 static int snmp_validate(ServiceValidationArgs* args)
  379 {
  380     ServiceSNMPData *sd;
  381     ServiceSNMPData *tmp_sd;
  382     tAppIdData *pf;
  383     uint8_t pdu;
  384     sfaddr_t *sip;
  385     sfaddr_t *dip;
  386     uint8_t version;
  387     const char *version_str = NULL;
  388     tAppIdData *flowp = args->flowp;
  389     const uint8_t *data = args->data;
  390     SFSnortPacket *pkt = args->pkt; 
  391     const int dir = args->dir;
  392     uint16_t size = args->size;
  393     bool app_id_debug_session_flag = args->app_id_debug_session_flag;
  394     char* app_id_debug_session = args->app_id_debug_session;
  395 
  396     if (!size)
  397         goto inprocess;
  398 
  399     sd = snmp_service_mod.api->data_get(flowp, snmp_service_mod.flow_data_index);
  400     if (!sd)
  401     {
  402         sd = calloc(1, sizeof(*sd));
  403         if (!sd)
  404             return SERVICE_ENOMEM;
  405         if (snmp_service_mod.api->data_add(flowp, sd, snmp_service_mod.flow_data_index, &free))
  406         {
  407             free(sd);
  408             return SERVICE_ENOMEM;
  409         }
  410         sd->state = SNMP_STATE_CONNECTION;
  411     }
  412 
  413     if (snmp_verify_packet(&data, data+size, &pdu, &version))
  414     {
  415         if (app_id_debug_session_flag)
  416             _dpd.logMsg("AppIdDbg %s snmp payload verify failed\n", app_id_debug_session);
  417         if (getAppIdFlag(flowp, APPID_SESSION_UDP_REVERSED))
  418         {
  419             if (dir == APP_ID_FROM_RESPONDER) goto bail;
  420             else goto fail;
  421         }
  422         else
  423         {
  424             if (dir == APP_ID_FROM_RESPONDER) goto fail;
  425             else goto bail;
  426         }
  427     }
  428 
  429     if (app_id_debug_session_flag)
  430         _dpd.logMsg("AppIdDbg %s snmp state %d\n", app_id_debug_session, sd->state);
  431 
  432     switch (sd->state)
  433     {
  434     case SNMP_STATE_CONNECTION:
  435         if (pdu != SNMP_PDU_GET_RESPONSE && dir == APP_ID_FROM_RESPONDER)
  436         {
  437             sd->state = SNMP_STATE_R_RESPONSE;
  438             setAppIdFlag(flowp, APPID_SESSION_UDP_REVERSED);
  439             break;
  440         }
  441         if (pdu == SNMP_PDU_GET_RESPONSE && dir == APP_ID_FROM_INITIATOR)
  442         {
  443             sd->state = SNMP_STATE_R_REQUEST;
  444             setAppIdFlag(flowp, APPID_SESSION_UDP_REVERSED);
  445             break;
  446         }
  447 
  448         if (dir == APP_ID_FROM_RESPONDER)
  449         {
  450             sd->state = SNMP_STATE_REQUEST;
  451             break;
  452         }
  453 
  454         if (pdu == SNMP_PDU_TRAP || pdu == SNMP_PDU_TRAPV2)
  455         {
  456             setAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_NOT_A_SERVICE);
  457             clearAppIdFlag(flowp, APPID_SESSION_CONTINUE);
  458             flowp->serviceAppId = APP_ID_SNMP;
  459             break;
  460         }
  461         sd->state = SNMP_STATE_RESPONSE;
  462 
  463         /*adding expected connection in case the server doesn't send from 161*/
  464         dip = GET_DST_IP(pkt);
  465         sip = GET_SRC_IP(pkt);
  466         pf = snmp_service_mod.api->flow_new(flowp, pkt, dip, 0, sip, pkt->src_port, flowp->proto, app_id, 0);
  467         if (pf)
  468         {
  469             tmp_sd = calloc(1, sizeof(ServiceSNMPData));
  470             if (tmp_sd == NULL) return SERVICE_ENOMEM;
  471             tmp_sd->state = SNMP_STATE_RESPONSE;
  472 
  473             if (snmp_service_mod.api->data_add(pf, tmp_sd, snmp_service_mod.flow_data_index, &free))
  474             {
  475                 free(tmp_sd);
  476                 return SERVICE_ENOMEM;
  477             }
  478             if (snmp_service_mod.api->data_add_id(pf, pkt->dst_port, &svc_element))
  479             {
  480                 setAppIdFlag(pf, APPID_SESSION_SERVICE_DETECTED);
  481                 clearAppIdFlag(pf, APPID_SESSION_CONTINUE);
  482                 tmp_sd->state = SNMP_STATE_ERROR;
  483                 return SERVICE_ENULL;
  484             }
  485             PopulateExpectedFlow(flowp, pf, APPID_SESSION_EXPECTED_EVALUATE, APP_ID_APPID_SESSION_DIRECTION_MAX);
  486             pf->rnaServiceState = RNA_STATE_STATEFUL;
  487             pf->scan_flags |= SCAN_HOST_PORT_FLAG;
  488             sfaddr_copy_to_raw(&pf->common.initiator_ip, sip);
  489        }
  490         break;
  491     case SNMP_STATE_RESPONSE:
  492         if (pdu == SNMP_PDU_GET_RESPONSE)
  493         {
  494             if (dir == APP_ID_FROM_RESPONDER) goto success;
  495             goto fail;
  496         }
  497         if (dir == APP_ID_FROM_RESPONDER) goto fail;
  498         break;
  499     case SNMP_STATE_REQUEST:
  500         if (pdu != SNMP_PDU_GET_RESPONSE)
  501         {
  502             if (dir == APP_ID_FROM_INITIATOR) goto success;
  503             goto fail;
  504         }
  505         if (dir == APP_ID_FROM_INITIATOR) goto fail;
  506         break;
  507     case SNMP_STATE_R_RESPONSE:
  508         if (pdu == SNMP_PDU_GET_RESPONSE)
  509         {
  510             if (dir == APP_ID_FROM_INITIATOR) goto success;
  511             goto fail;
  512         }
  513         if (dir == APP_ID_FROM_INITIATOR) goto fail;
  514         break;
  515     case SNMP_STATE_R_REQUEST:
  516         if (pdu != SNMP_PDU_GET_RESPONSE)
  517         {
  518             if (dir == APP_ID_FROM_RESPONDER) goto success;
  519             goto fail;
  520         }
  521         if (dir == APP_ID_FROM_RESPONDER) goto fail;
  522         break;
  523     default:
  524         if (dir == APP_ID_FROM_RESPONDER) goto fail;
  525         else goto bail;
  526     }
  527 
  528 inprocess:
  529     snmp_service_mod.api->service_inprocess(flowp, pkt, dir, &svc_element, NULL);
  530     return SERVICE_INPROCESS;
  531 
  532 success:
  533     switch (version)
  534     {
  535     case SNMP_VERSION_1:
  536         version_str = SNMP_VERSION_STR_1;
  537         break;
  538     case SNMP_VERSION_2c:
  539         version_str = SNMP_VERSION_STR_2c;
  540         break;
  541     case SNMP_VERSION_2u:
  542         version_str = SNMP_VERSION_STR_2u;
  543         break;
  544     case SNMP_VERSION_3:
  545         version_str = SNMP_VERSION_STR_3;
  546         break;
  547     default:
  548         version_str = NULL;
  549         break;
  550     }
  551     snmp_service_mod.api->add_service(flowp, pkt, dir, &svc_element,
  552                                       APP_ID_SNMP,
  553                                       SNMP_VENDOR_STR, version_str, NULL, NULL);
  554     return SERVICE_SUCCESS;
  555 
  556 bail:
  557     snmp_service_mod.api->incompatible_data(flowp, pkt, dir, &svc_element,
  558                                             snmp_service_mod.flow_data_index,
  559                                             args->pConfig, NULL);
  560     return SERVICE_NOT_COMPATIBLE;
  561 
  562 fail:
  563     snmp_service_mod.api->fail_service(flowp, pkt, dir, &svc_element,
  564                                        snmp_service_mod.flow_data_index,
  565                                        args->pConfig, NULL);
  566     return SERVICE_NOMATCH;
  567 }
  568