⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spp_telnet_negotiation.c

📁 Linux snort-2.4.4源代码
💻 C
字号:
/*** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* Snort Preprocessor for Telnet Negotiation Normalization*//* $Id$ *//* spp_telnet_negotiation.c  *  * Purpose:  Telnet and FTP sessions can contain telnet negotiation strings  *           that can disrupt pattern matching.  This plugin detects  *           negotiation strings in stream and "normalizes" them much like *           the http_decode preprocessor normalizes encoded URLs * * * http://www.iana.org/assignments/telnet-options  -- official registry of options * * * Arguments:  None *    * Effect:  The telnet nogiation data is removed from the payload * * Comments: * *//* your preprocessor header file goes here */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <sys/types.h>#include "decode.h"#include "plugbase.h"#include "parser.h"#include "log.h"#include "debug.h"#include "util.h"#include "mstring.h"#include "snort.h"extern u_int8_t DecodeBuffer[DECODE_BLEN]; /* decode.c *//* define the telnet negotiation codes (TNC) that we're interested in */#define TNC_IAC  0xFF#define TNC_SB   0xFA#define TNC_GA   0xF9#define TNC_EAL  0xF8#define TNC_EAC  0xF7#define TNC_AO   0xF6#define TNC_AYT  0xF5#define TNC_IP   0xF4#define TNC_BRK  0xF3#define TNC_DM   0xF2#define TNC_NOP  0xF1#define TNC_SE   0xF0#define TNC_STD_LENGTH  3/* list of function prototypes for this preprocessor */extern void TelNegInit(u_char *);extern void NormalizeTelnet(Packet *, void *);static void SetTelnetPorts(char *portlist);     /* array containing info about which ports we care about */static char TelnetDecodePorts[65536/8];/* * Function: SetupTelNeg() * * Purpose: Registers the preprocessor keyword and initialization  *          function into the preprocessor list.   * * Arguments: None. * * Returns: void function * */void SetupTelNeg(){    /* Telnet negotiation has many names, but we only implement this     * plugin for Bob Graham's benefit...     */     RegisterPreprocessor("telnet_decode", TelNegInit);    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Preprocessor: Telnet Decode Decode is setup...\n"););}/* * Function: TelNegInit(u_char *) * * Purpose: Calls the argument parsing function, performs final setup on data *          structs, links the preproc function into the function list. * * Arguments: args => ptr to argument string * * Returns: void function * */void TelNegInit(u_char *args){    DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Preprocessor: TelNeg Initialized\n"););    SetTelnetPorts(args);    /* Set the preprocessor function into the function list */    AddFuncToPreprocList(NormalizeTelnet);}/* * Function: PreprocFunction(Packet *) * * Purpose: Perform the preprocessor's intended function.  This can be *          simple (statistics collection) or complex (IP defragmentation) *          as you like.  Try not to destroy the performance of the whole *          system by trying to do too much.... * * Arguments: p => pointer to the current packet data struct  * * Returns: void function * */void NormalizeTelnet(Packet *p, void *context){    char *read_ptr;    char *start = (char *) DecodeBuffer; /* decode.c */    char *write_ptr;    char *end;    int normalization_required = 0;    if(!(p->preprocessors & PP_TELNEG))    {        return;    }        /* check for TCP traffic that's part of an established session */    if(!PacketIsTCP(p))    {        return;    }    /* check the port list */    if(!(TelnetDecodePorts[(p->dp/8)] & (1<<(p->dp%8))))    {        return;    }    /* negotiation strings are at least 3 bytes long */    /* other telnet commands are handled in here, too, and     * They can be 2 bytes long -- ie, IAC NOP, IAC AYT, etc. */    if(p->dsize < TNC_STD_LENGTH)    {        return;    }    /* setup the pointers */    read_ptr = p->data;    end = p->data + p->dsize;        /* look to see if we have any telnet negotiaion codes in the payload */    while(!normalization_required && (read_ptr < end))    {        /* look for the start of a negotiation string */        if(*read_ptr == (char) TNC_IAC)        {            /* set a flag for stage 2 normalization */            normalization_required = 1;        }        read_ptr++;    }    if(!normalization_required)    {        DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Nothing to process!\n"););        return;    }    /*     * if we found telnet negotiation strings OR backspace characters,     * we're going to have to normalize the data     *     * Note that this is always ( now: 2002-08-12 ) done to a     * alternative data buffer.     */        /* rewind the data stream to p->data */    read_ptr = p->data;        /* setup for overwriting the negotaiation strings with      * the follow-on data     */     write_ptr = (char *) DecodeBuffer;        /* walk thru the remainder of the packet */    while((read_ptr < end) && (write_ptr < ((char *) DecodeBuffer) + DECODE_BLEN))    {                 /* if the following byte isn't a subnegotiation initialization */        if(((read_ptr + 1) < end) &&           (*read_ptr == (char) TNC_IAC) &&           (*(read_ptr + 1) != (char) TNC_SB))        {            /* NOPs are two bytes long */            switch(* ((unsigned char *)(read_ptr + 1)))            {            case TNC_NOP:                read_ptr += 2;                break;            case TNC_EAC:                read_ptr += 2;                /* wind it back a character */                if(write_ptr  > start)                {                    write_ptr--;                }                break;            case TNC_EAL:                /* todo: wind write_ptr back a line? */                read_ptr += 2;                break;            case TNC_SE:                /* Uh, what the heck is a Subnegotiation-end                 * doing here without a SB?.                 * could generate an alert, or just normalize                 * it out.                 */                read_ptr += 2;                break;            /* These are two bytes long */            case TNC_BRK:            case TNC_DM:            case TNC_IP:            case TNC_AO:            case TNC_AYT:            case TNC_GA:                read_ptr += 2;                break;            /* IAC IAC -- means the IAC character (0xff) should be             * in the data stream since it was escaped */            case TNC_IAC:                read_ptr++; /* skip past the first IAC */                *write_ptr++ = *read_ptr++;                break;            default: /* WILL, WON'T, DO, DON'T */                /* move the read ptr up 3 bytes */                read_ptr += TNC_STD_LENGTH;            }                        }        /* check for subnegotiation */        else if(((read_ptr + 1) < end) &&                (*read_ptr == (char) TNC_IAC) &&                (*(read_ptr+1) == (char) TNC_SB))        {            /* move to the end of the subneg */            do            {                read_ptr++;            } while((*read_ptr != (char) TNC_SE) && (read_ptr < end));            if (*read_ptr == (char)TNC_SE)                read_ptr++; /* Skip past the TNC_SE */        }        else        {            DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "overwriting %2X(%c) with %2X(%c)\n",                                    (char)(*write_ptr&0xFF), *write_ptr,                                     (char)(*read_ptr & 0xFF), *read_ptr););                        /* overwrite the negotiation bytes with the follow-on bytes */            *write_ptr++ = *read_ptr++;        }    }        p->packet_flags |= PKT_ALT_DECODE;        p->alt_dsize = write_ptr - start;        /* DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,                             "Converted buffer after telnet normalization:\n");               PrintNetData(stdout, (char *) DecodeBuffer, p->alt_dsize););    */    return;}/* * Function: SetTelnetPorts(char *) * * Purpose: Reads the list of port numbers from the argument string and  *          parses them into the port list data struct * * Arguments: portlist => argument list * * Returns: void function * */static void SetTelnetPorts(char *portlist){    char portstr[STD_BUF];    char **toks;    int is_reset = 0;    int num_toks = 0;    int num = 0;    if(portlist == NULL || *portlist == '\0')    {        portlist = "21 23 25 119";    }        /* tokenize the argument list */    toks = mSplit(portlist, " ", 31, &num_toks, '\\');    LogMessage("telnet_decode arguments:\n");    /* convert the tokens and place them into the port list */    for(num = 0; num < num_toks; num++)    {        if(isdigit((int)toks[num][0]))        {            char *num_p = NULL; /* used to determine last position in string */            long t_num;                    t_num = strtol(toks[num], &num_p, 10);                    if(*num_p != '\0')            {                FatalError("Port Number invalid format: %s\n", toks[num]);            }            else if(t_num < 0 || t_num > 65335)            {                FatalError("Port Number out of range: %ld\n", t_num);            }                    /* user specified a legal port number and it should override the default               port list, so reset it unless already done */            if(!is_reset)            {                bzero(&TelnetDecodePorts, sizeof(TelnetDecodePorts));                portstr[0] = '\0';                is_reset = 1;            }                    /* mark this port as being interesting using some portscan2-type voodoo,                and also add it to the port list string while we're at it so we can               later print out all the ports with a single LogMessage() */            TelnetDecodePorts[(t_num/8)] |= 1<<(t_num%8);            if(strlcat(portstr, toks[num], STD_BUF - 1) >= STD_BUF)            {                FatalError("%s(%d) Portstr is truncated!\n", file_name, file_line);            }                                    if(strlcat(portstr, " ", STD_BUF - 1) >= STD_BUF)            {                FatalError("%s(%d) Portstr is truncated!\n", file_name, file_line);            }        }        else        {            FatalError(" %s(%d) => Unknown argument to telnet_decode "                       "preprocessor: \"%s\"\n",                        file_name, file_line, toks[num]);        }    }        mSplitFree(&toks, num_toks);    /* print out final port list */    LogMessage("    Ports to decode telnet on: %s\n", portstr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -