Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

sp_session.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00005 **
00006 ** This program is free software; you can redistribute it and/or modify
00007 ** it under the terms of the GNU General Public License as published by
00008 ** the Free Software Foundation; either version 2 of the License, or
00009 ** (at your option) any later version.
00010 **
00011 ** This program is distributed in the hope that it will be useful,
00012 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 ** GNU General Public License for more details.
00015 **
00016 ** You should have received a copy of the GNU General Public License
00017 ** along with this program; if not, write to the Free Software
00018 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 */
00020 
00021 /* Snort Session Logging Plugin */
00022 
00023 /* sp_session 
00024  * 
00025  * Purpose:
00026  *
00027  * Drops data (printable or otherwise) into a SESSION file.  Useful for 
00028  * logging user sessions (telnet, http, ftp, etc).
00029  *
00030  * Arguments:
00031  *   
00032  * This plugin can take two arguments:
00033  *    printable => only log the "printable" ASCII characters.
00034  *    all       => log all traffic in the session, logging non-printable
00035  *                 chars in "\xNN" hexidecimal format
00036  *
00037  * Effect:
00038  *
00039  * Warning, this plugin may slow Snort *way* down!
00040  *
00041  */
00042 
00043 /* put the name of your pluging header file here */
00044 #ifdef HAVE_CONFIG_H
00045 #include "config.h"
00046 #endif
00047 
00048 
00049 #include <sys/types.h>
00050 #ifndef WIN32
00051 #include <sys/socket.h>
00052 #include <netinet/in.h>
00053 #include <arpa/inet.h>
00054 #endif /* !WIN32 */
00055 #include <stdio.h>
00056 #include <stdlib.h>
00057 #include <ctype.h>
00058 #include <string.h>
00059 
00060 #ifdef HAVE_STRINGS_H
00061 #include <strings.h>
00062 #endif
00063 
00064 #include <errno.h>
00065 #include <sys/stat.h>
00066 
00067 #include "rules.h"
00068 #include "decode.h"
00069 #include "plugbase.h"
00070 #include "parser.h"
00071 #include "debug.h"
00072 #include "util.h"
00073 #include "plugin_enum.h"
00074 #include "snort.h"
00075 
00076 
00077 #define SESSION_PRINTABLE  1
00078 #define SESSION_ALL        2
00079 #define SESSION_BINARY     3
00080 
00081 typedef struct _SessionData
00082 {
00083     int session_flag;
00084 } SessionData;
00085 
00086 void SessionInit(char *, OptTreeNode *, int);
00087 void ParseSession(char *, OptTreeNode *);
00088 int LogSessionData(Packet *, struct _OptTreeNode *, OptFpList *);
00089 void DumpSessionData(FILE *, Packet *, struct _OptTreeNode *);
00090 FILE *OpenSessionFile(Packet *);
00091 
00092 
00093 /****************************************************************************
00094  * 
00095  * Function: SetupSession()
00096  *
00097  * Purpose: Init the session plugin module.
00098  *
00099  * Arguments: None.
00100  *
00101  * Returns: void function
00102  *
00103  ****************************************************************************/
00104 void SetupSession(void)
00105 {
00106     /* map the keyword to an initialization/processing function */
00107     RegisterPlugin("session", SessionInit);
00108     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: Session Setup\n"););
00109 }
00110 
00111 
00112 /**************************************************************************
00113  * 
00114  * Function: SessionInit(char *, OptTreeNode *)
00115  *
00116  * Purpose: Initialize the sesion plugin, parsing the rule parameters and
00117  *          setting up any necessary data structures.
00118  *
00119  * Arguments: data => rule arguments/data
00120  *            otn => pointer to the current rule option list node
00121  *
00122  * Returns: void function
00123  *
00124  *************************************************************************/
00125 void SessionInit(char *data, OptTreeNode *otn, int protocol)
00126 {
00127 
00128     /*
00129      * Theoretically we should only all this plugin to be used when there's a 
00130      * possibility of a session happening (i.e. TCP), but I get enough 
00131      * requests that I'm going to pull the verifier so that things should work
00132      * for everyone
00133      */
00134 /*    if(protocol != IPPROTO_TCP)
00135     {
00136         FatalError("%(%d): Session keyword can not be used in non-TCP rule\n",
00137                 file_name, file_line);
00138     }*/
00139 
00140     /* multiple declaration check */ 
00141     if(otn->ds_list[PLUGIN_SESSION])
00142     {
00143         FatalError("%s(%d): Multiple session options in rule\n", file_name,
00144                 file_line);
00145     }
00146 
00147     /* allocate the data structure and attach it to the
00148        rule's data struct list */
00149     otn->ds_list[PLUGIN_SESSION] = (SessionData *)
00150         SnortAlloc(sizeof(SessionData));
00151 
00152     /* be sure to check that the protocol that is passed in matches the
00153        transport layer protocol that you're using for this rule! */
00154 
00155     /* this is where the keyword arguments are processed and placed into 
00156        the rule option's data structure */
00157     ParseSession(data, otn);
00158 
00159     /* finally, attach the option's detection function to the rule's 
00160        detect function pointer list */
00161     AddOptFuncToList(LogSessionData, otn);
00162 }
00163 
00164 
00165 
00166 /****************************************************************************
00167  * 
00168  * Function: ParseSession(char *, OptTreeNode *)
00169  *
00170  * Purpose: Figure out how much of the session data we're collecting
00171  *
00172  * Arguments: data => argument data
00173  *            otn => pointer to the current rule's OTN
00174  *
00175  * Returns: void function
00176  *
00177  ****************************************************************************/
00178 void ParseSession(char *data, OptTreeNode *otn)
00179 {
00180     SessionData *ds_ptr;  /* data struct pointer */
00181 
00182     /* set the ds pointer to make it easier to reference the option's
00183        particular data struct */
00184     ds_ptr = otn->ds_list[PLUGIN_SESSION];
00185 
00186     /* manipulate the option arguments here */
00187     while(isspace((int)*data))
00188         data++;
00189 
00190     if(!strncasecmp(data, "printable", 9))
00191     {
00192         ds_ptr->session_flag = SESSION_PRINTABLE;
00193         return;
00194     }
00195 
00196     if(!strncasecmp(data, "binary", 6))
00197     {
00198         ds_ptr->session_flag = SESSION_BINARY;
00199         return;
00200     }
00201 
00202     if(!strncasecmp(data, "all", 3))
00203     {
00204         ds_ptr->session_flag = SESSION_ALL;
00205         return;
00206     }
00207 
00208     FatalError("%s(%d): invalid session modifier: %s\n", file_name, file_line, data);
00209 
00210 }
00211 
00212 
00213 
00214 /****************************************************************************
00215  * 
00216  * Function: LogSessionData(char *, OptTreeNode *)
00217  *
00218  * Purpose: Dumps the session data to the log file.
00219  *
00220  * Arguments: data => argument data
00221  *            otn => pointer to the current rule's OTN
00222  *
00223  * Returns: Always calls the next function (this one doesn't test the data,
00224  *          it just logs it....)
00225  *
00226  ****************************************************************************/
00227 int LogSessionData(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00228 {
00229     FILE *session;         /* session file ptr */
00230 
00231     /* if there's data in this packet */
00232     if((p != NULL && p->dsize != 0 && p->data != NULL) || p->frag_flag != 1)
00233     {
00234         session = OpenSessionFile(p);
00235 
00236         if(session == NULL)
00237         {
00238             return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00239         }
00240 
00241         DumpSessionData(session, p, otn);
00242 
00243         fclose(session);
00244     }
00245 
00246     return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00247 }
00248 
00249 
00250 
00251 void DumpSessionData(FILE *fp, Packet *p, struct _OptTreeNode *otn)
00252 {
00253     u_char *idx;
00254     u_char *end;
00255     char conv[] = "0123456789ABCDEF"; /* xlation lookup table */
00256 
00257     if(p->dsize == 0 || p->data == NULL || p->frag_flag)
00258         return;
00259 
00260     idx = p->data;
00261     end = idx + p->dsize;
00262 
00263     if(((SessionData *) otn->ds_list[PLUGIN_SESSION])->session_flag == SESSION_PRINTABLE)
00264     {
00265         while(idx != end)
00266         {
00267             if((*idx > 0x1f && *idx < 0x7f) || *idx == 0x0a || *idx == 0x0d)
00268             {
00269                 fputc(*idx, fp);
00270             }
00271             idx++;
00272         }
00273     }
00274     else if(((SessionData *) otn->ds_list[PLUGIN_SESSION])->session_flag == SESSION_BINARY)
00275     {
00276         fwrite(p->data, p->dsize, sizeof(char), fp);
00277     }
00278     else
00279     {
00280         while(idx != end)
00281         {
00282             if((*idx > 0x1f && *idx < 0x7f) || *idx == 0x0a || *idx == 0x0d)
00283             {
00284                 /* Escape all occurences of '\' */
00285                 if(*idx == '\\')
00286                     fputc('\\', fp);
00287                 fputc(*idx, fp);
00288             }
00289             else
00290             {
00291                 fputc('\\', fp);
00292                 fputc(conv[((*idx&0xFF) >> 4)], fp);
00293                 fputc(conv[((*idx&0xFF)&0x0F)], fp);
00294             }
00295 
00296             idx++;
00297         }
00298     }
00299 }
00300 
00301 
00302 
00303 FILE *OpenSessionFile(Packet *p)
00304 {
00305     char filename[STD_BUF];
00306     char log_path[STD_BUF];
00307     char session_file[STD_BUF]; /* name of session file */
00308     FILE *ret;
00309 
00310     if(p->frag_flag)  
00311     {
00312         return NULL;
00313     }
00314 
00315     bzero((char *)session_file, STD_BUF);
00316     bzero((char *)log_path, STD_BUF);
00317 
00318     /* figure out which way this packet is headed in relation to the homenet */
00319     if((p->iph->ip_dst.s_addr & pv.netmask) == pv.homenet)
00320     {
00321         if((p->iph->ip_src.s_addr & pv.netmask) != pv.homenet)
00322         {
00323             sprintf(log_path, "%s/%s", pv.log_dir, inet_ntoa(p->iph->ip_src));
00324         }
00325         else
00326         {
00327             if(p->sp >= p->dp)
00328             {
00329                 sprintf(log_path, "%s/%s", pv.log_dir, inet_ntoa(p->iph->ip_src));
00330             }
00331             else
00332             {
00333                 sprintf(log_path, "%s/%s", pv.log_dir, inet_ntoa(p->iph->ip_dst));
00334             }
00335         }
00336     }
00337     else
00338     {
00339         if((p->iph->ip_src.s_addr & pv.netmask) == pv.homenet)
00340         {
00341             sprintf(log_path, "%s/%s", pv.log_dir, inet_ntoa(p->iph->ip_dst));
00342         }
00343         else
00344         {
00345             if(p->sp >= p->dp)
00346             {
00347                 sprintf(log_path, "%s/%s", pv.log_dir, inet_ntoa(p->iph->ip_src));
00348             }
00349             else
00350             {
00351                 sprintf(log_path, "%s/%s", pv.log_dir, inet_ntoa(p->iph->ip_dst));
00352             }
00353         }
00354     }
00355 
00356     /* build the log directory */
00357     if(mkdir(log_path,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
00358     {
00359         if(errno != EEXIST)
00360         {
00361             FatalError("Problem creating directory %s: %s\n",
00362                        log_path,strerror(errno));
00363         }
00364     }
00365 
00366     if(p->sp >= p->dp)
00367     {
00368 #ifdef WIN32
00369         sprintf(session_file, "%s/SESSION_%d-%d", log_path, p->sp, p->dp);
00370 #else
00371         sprintf(session_file, "%s/SESSION:%d-%d", log_path, p->sp, p->dp);
00372 #endif
00373     }
00374     else
00375     {
00376 #ifdef WIN32
00377         sprintf(session_file, "%s/SESSION_%d-%d", log_path, p->dp, p->sp);
00378 #else
00379         sprintf(session_file, "%s/SESSION:%d-%d", log_path, p->dp, p->sp);
00380 #endif
00381     }
00382 
00383     
00384     strncpy(filename, session_file, STD_BUF - 1);
00385     filename[STD_BUF - 1] = '\0';
00386 
00387     ret = fopen(session_file, "a");
00388 
00389     if(ret == NULL)
00390     {
00391         FatalError("OpenSessionFile() => fopen(%s) session file: %s\n",
00392                    session_file, strerror(errno));
00393     }
00394 
00395     return ret;
00396 
00397 }
00398 
00399 
00400 
00401 

Generated on Sun May 14 14:51:13 2006 by  doxygen 1.4.2