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

📄 spp_tcp_stream.c

📁 该源码是用C语言编写的,实现网络入侵检测系统的功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** Copyright (C) 1998,1999,2000,2001 Martin Roesch <roesch@clark.net>** Copyright (C) 1999,2000,2001 Christopher E. Cramer <cec@ee.duke.edu>** ** 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.*//* $Id: spp_tcp_stream.c,v 1.14 2001/01/18 21:49:06 cec Exp $ *//* spp_tcp_stream *  * Purpose: * * Construct tcp streams from observed packets * * Usage: * * preprocessor stream: <arg set 1>, <arg set 2>, ... * * Arguments:  one or more of the following separated by commas * * timeout <timeout value> * * ports <port 1> ... <port N> * * maxbytes <maxbytes> * * <timeout>  - the max time in seconds for which a stream will be  *            kept alive if we haven't seen a packet for it * <port x>   - a server port to monitor.  we don't want to monitor  *            all tcp streams (do we?) * <maxbytes> - maximum bytes in our reconstructed packets * *     example:  *       preprocessor stream: timeout 5, ports 21 23 80 8080, maxbytes 16384 * * Effect: * * creates a buffer for each observed tcp stream.  upon seeing a RETURN  * or receiving a maximum number of bytes, generate a packet containing  * the reconstructed data * * Comments: * * the size of <timeout> will directly impact the amount of memory used.   * The longer the timeout the more streams kept in memory, the greater  * the memory usage. * * To Do:  *    make buffers circular to avoid copying *    check RST packets to verify sequence number *    allow tighter checks on what we monitor - reduce memory usage. * */#include "spp_tcp_stream.h"#ifndef WIN32       #include <strings.h>       #include <sys/time.h>#else       #include <time.h>#endif#include <sys/types.h>#undef HAVE_64/* external globals from rules.c */extern char *file_name;extern int file_line;TcpStreamData StreamData;FILE *TcpStreamFile;int sesscount = 0;/* * Function: SetupTcpStream() * * Purpose: Registers the preprocessor keyword and initialization  *          function into the preprocessor list.  This is the function that *          gets called from InitPreprocessors() in plugbase.c. * * Arguments: None. * * Returns: void function * */void SetupTcpStream(){    /* link the preprocessor keyword to the init function in        the preproc list */    RegisterPreprocessor("stream", TcpStreamInit);#ifdef DEBUG    printf("Preprocessor: TcpStream is setup...\n");#endif}/* * Function: TcpStreamInit(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 TcpStreamInit(u_char *args){    int i;#ifdef DEBUG    printf("Preprocessor: TcpStream Initialized\n");#endif    /* parse the argument list from the rules file */    for(i=0;i<256;i++)        StreamData.heads[i] = (TcpStreamSession *)NULL;    ParseTcpStreamArgs(args);    /* Set the preprocessor function into the function list */    AddFuncToPreprocList(TcpStreamPacket);}/* * Function: ParseTcpStreamArgs(char *) * * Purpose: Process the preprocessor arguements from the rules file and  *          initialize the preprocessor's data struct.  This function doesn't *          have to exist if it makes sense to parse the args in the init  *          function. * * Arguments: args => argument list * * Returns: void function * */void ParseTcpStreamArgs(char *args){    /* your parsing function goes here, check out the other spp files       for examples */    char **toks, **secs;    int num_toks, num_secs;    int i,j;    if(args == NULL)    {        FatalError("ERROR %s (%d)=> No arguments to TcpStream preprocessor!\n", file_name, file_line);    }    StreamData.maxbytes = 0x01<<12;    StreamData.prunetime = 10;    /* tokenize the argument list */    secs = mSplit(args, ",", 33, &num_secs, '\\');    for(i=0;i<num_secs;i++)    {        toks = mSplit(secs[i], " ", 33, &num_toks, '\\');        if(strcmp(toks[0],"timeout") == 0)        {            if(num_toks != 2) FatalError("ERROR %s (%d)=> timeout takes 1 argument!\n",file_name,file_line);            StreamData.prunetime = atoi(toks[1]);            if(StreamData.prunetime <= 0)            {                FatalError("ERROR %s (%d)=> Time between prunings must be >0 seconds!\n",file_name,file_line);            }        }        else if(strcmp(toks[0],"maxbytes") == 0)        {            if(num_toks != 2) FatalError("ERROR %s (%d)=> maxbytes takes 1 argument!\n",file_name,file_line);            StreamData.maxbytes = atoi(toks[1]);            if(StreamData.maxbytes < 0 || StreamData.maxbytes > (0x1 << 15))            {                FatalError("ERROR %s (%d)=> maxbytes must be >= 0 and <= 32K bytes!\n",file_name,file_line);            }        }        else if(strcmp(toks[0],"ports") == 0)        {            for(j = 1; j < num_toks; j++)            {                StreamData.ports[j-1] = atoi(toks[j]);            }               StreamData.num_entries = num_toks-1;        }        else        {            FatalError("ERROR %s (%d)=> unknown argument to preprocessor stream: %s!\n",file_name,file_line,toks[0]);        }        for(j=0;j<num_toks;j++)            free(toks[j]);    }    for(i=0;i<num_secs;i++)        free(secs[i]);}/* * Function: TcpStreamPacket(Packet *) * * Purpose:  take a packet, determine if it is tcp.  if so, is it the start of a stream? *           yes - create new stream.  no - do we have that stream?  yes - deal w/ packet. *           no - return * * * Arguments: p => pointer to the current packet data struct  * * Returns: void function * */void TcpStreamPacket(Packet *p){    int i;    int pos;#ifdef DEBUG    char sip[16];    char dip[16];#endif    u_long tm;    TcpStreamSession * sptr = NULL;    u_int32_t lack, lseq;    int server_packet;    u_long bytes_in_buf, made_packet;    int bin;    /* statuses (client-status & server-status) from TCP/IP Illustrated v1, p 241:       0 - closed       1 - listen       2 - SYN_RCVD       3 - SYN_SENT       4 - ESTABLISHED  (data xfer mode)       5 - CLOSE_WAIT       6 - LAST_ACK       7 - FIN_WAIT_1       8 - CLOSING       9 - FIN_WAIT_2       10- TIME_WAIT    */    if(!PacketIsTCP(p))    {#ifdef DEBUG        printf("It isn't TCP session traffic\n");#endif        return;    }    /* don't accept packets w/ bad checksums */    if(p->csum_flags & CSE_IP || p->csum_flags & CSE_TCP)    {#ifdef DEBUG        printf("Discarding packet based on checksum errors!\n");#endif        return;    }    if(p->tcph->th_ack == 0 && p->tcph->th_seq == 0)    {#ifdef DEBUG        printf("TcpStream Preprocessor shouldn't be handling it's own packets! :-)\n");#endif        return;    }    for(i = 0; i < StreamData.num_entries; i++)        if((StreamData.ports[i] == p->dp) || (StreamData.ports[i] == p->sp)) break;    if(i == StreamData.num_entries) return;  /* not a monitored port */    pc.tcp_stream_pkts ++;  /* a packet we use */    if(StreamData.ports[i] == p->sp)    {        server_packet = 1;    }    else    {        server_packet = 0;    }    tm = TcpStreamTime();    if(tm - StreamData.timestamp >= StreamData.prunetime)    {        TcpStreamPruneSessions();        StreamData.timestamp = tm;    }    lack = ntohl(p->tcph->th_ack);    lseq = ntohl(p->tcph->th_seq);#if DEBUG    strncpy(sip, inet_ntoa(p->iph->ip_src), 16);    strncpy(dip, inet_ntoa(p->iph->ip_dst), 16);    printf("Packet (%x %u/%u %i) - %s:%i -> %s:%i (%i)\n",p->tcph->th_flags,lseq,lack,p->tcph->th_win,sip,p->sp,dip,p->dp,p->dsize);#endif     sptr = TcpStreamCheckSession(p,StreamData.ports[i], &bin);    if(sptr == (TcpStreamSession *)NULL)    {        if(p->tcph->th_flags == R_SYN)        { /* new stream, SYN packet */            sptr = (TcpStreamSession *)malloc(sizeof(TcpStreamSession));            sptr->next = StreamData.heads[bin];            StreamData.heads[bin] = sptr;            pc.tcp_streams ++;  /* new tcp stream */            sptr->client_status = SYN_SENT;            sptr->server_status = SYN_RCVD;            sptr->c_inbuf = sptr->s_inbuf = 0;            sptr->cip = p->iph->ip_src.s_addr;            sptr->cp = p->sp;            sptr->sip = p->iph->ip_dst.s_addr;            sptr->sp = p->dp;            sptr->c_first_seq = lseq + 1;            sptr->c_last_acked = lseq + 1; /* cheat mode */            sptr->c_buf_start = lseq + 1;            sptr->c_last_byte = sptr->s_last_byte = 0;            sptr->timestamp = tm;            sptr->c_buf = NULL;            sptr->s_buf = NULL;            if(p->tcph->th_win > 0)            {                sptr->c_buf_siz = ntohs(p->tcph->th_win) + StreamData.maxbytes;                sptr->c_buf = (u_char *)malloc(sptr->c_buf_siz);                sptr->c_buf_allocd = 1;            }            else            {                sptr->c_buf_allocd = 0;            }            sptr->s_buf_allocd = 0;        }        return; /* either way, we are done here */    }    sptr->timestamp = tm;    if(p->tcph->th_flags == R_SYN)    /* j'accuse - we have a stream, but */        return;                           /* we've been sent a SYN - spoofer */    if(p->tcph->th_flags & R_RST)    {  /* handle RST by putting going to CLOSED state */        sptr->client_status = CLOSED;        sptr->server_status = CLOSED;        sptr->c_inbuf = sptr->s_inbuf = 0;        sptr->c_first_seq = lseq + 1;        sptr->c_last_acked = lseq + 1; /* cheat mode */        sptr->c_last_byte = sptr->s_last_byte = 0;        sptr->timestamp = tm;        return;    }    if(p->tcph->th_flags == (R_SYN | R_ACK))    { /* SYN/ACK */        if(!server_packet) return;  /* Client should not SYN/ACK */        if(lack != sptr->c_first_seq) return; /* False SYN/ACK - bad seq*/        if((sptr->client_status == SYN_SENT) && (sptr->server_status = SYN_RCVD))        {            sptr->s_first_seq = lseq+1;            sptr->s_last_acked = lseq+1; /* cheat mode on */            sptr->s_buf_start = lseq+1;            sptr->client_status = ESTABLISHED; /* client happy, should send ACK */            if(p->tcph->th_win != 0)            {                sptr->s_buf_siz = ntohs(p->tcph->th_win) + StreamData.maxbytes;                sptr->s_buf = (u_char *) malloc(sptr->s_buf_siz);                sptr->s_buf_allocd = 1;            }        }        return;    }    /* If buffers haven't been allocated, try to do so here */    if(!server_packet && !sptr->c_buf_allocd)    {        if(p->tcph->th_win != 0)        {            sptr->c_buf_siz = ntohs(p->tcph->th_win) + StreamData.maxbytes;            sptr->c_buf = (u_char *) malloc(sptr->c_buf_siz);            sptr->c_buf_allocd = 1;        }    }    if(server_packet && !sptr->s_buf_allocd)    {        if(p->tcph->th_win != 0)        {            sptr->s_buf_siz = ntohs(p->tcph->th_win) + StreamData.maxbytes;            sptr->s_buf = (u_char *) malloc(sptr->s_buf_siz);            sptr->s_buf_allocd = 1;        }    }#if DEBUG    printf("statuses: %i/%i\n",sptr->server_status, sptr->client_status);#endif    /* Check here to see if we inject new server packet */    if(!server_packet && sptr->server_status >= ESTABLISHED)    {  /* check to see if server buffer has proper data */        if(lack - sptr->s_first_seq > 0x7fffffff) bytes_in_buf = 0;        else bytes_in_buf = lack - sptr->s_first_seq;        /* shouldn't happen in a sane world */        if(bytes_in_buf > sptr->s_buf_siz)        {#ifdef DEBUG            ErrorMessage("[!] WARNING: TCP stream reassembler, Server Bytes in Buffer > Buffer Size (%i > %i)\n", bytes_in_buf, sptr->s_buf_siz);#endif            bytes_in_buf = sptr->s_buf_siz;        }        made_packet = 0;        if(bytes_in_buf >= StreamData.maxbytes)        {            TcpStreamPacketize(p, sptr->s_buf, StreamData.maxbytes, server_packet);            made_packet = StreamData.maxbytes;        }        else        {            if (!sptr->s_buf_allocd)            {#ifdef DEBUG                printf("WARNING: TCP stream reassembler never got proper window size, setting to max!\n");#endif                sptr->s_buf_siz = 65536 + StreamData.maxbytes;                sptr->s_buf = (u_char *) malloc(sptr->s_buf_siz);                sptr->s_buf_allocd = 1;            }                        for(i=bytes_in_buf; i > (int)(sptr->s_last_acked - sptr->s_first_seq); i--)                if(sptr->s_buf[i-1] == 0xa || sptr->s_buf[i-1] == 0xd)                {                    TcpStreamPacketize(p, sptr->s_buf, i, server_packet);                    made_packet = i;                    break;                }        }

⌨️ 快捷键说明

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