00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifdef HAVE_CONFIG_H
00031 #include "config.h"
00032 #endif
00033
00034 #include <sys/types.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <ctype.h>
00038
00039 #include "rules.h"
00040 #include "decode.h"
00041 #include "plugbase.h"
00042 #include "parser.h"
00043 #include "debug.h"
00044 #include "util.h"
00045 #include "plugin_enum.h"
00046 #include "snort.h"
00047
00048
00049
00050 typedef struct _ClientServerData
00051 {
00052 u_int8_t from_server;
00053 u_int8_t from_client;
00054 u_int8_t ignore_reassembled;
00055 u_int8_t only_reassembled;
00056 } ClientServerData;
00057
00058 void FlowInit(char *, OptTreeNode *, int);
00059 void ParseFlowArgs(char *, OptTreeNode *);
00060 void InitFlowData(OptTreeNode *);
00061 int CheckFromClient(Packet *, struct _OptTreeNode *, OptFpList *);
00062 int CheckFromServer(Packet *, struct _OptTreeNode *, OptFpList *);
00063 int CheckForReassembled(Packet *, struct _OptTreeNode *, OptFpList *);
00064 int CheckForNonReassembled(Packet *p, struct _OptTreeNode *, OptFpList *);
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 void SetupClientServer(void)
00081 {
00082
00083 RegisterPlugin("flow", FlowInit);
00084
00085 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
00086 "Plugin: ClientServerName(Flow) Setup\n"););
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void FlowInit(char *data, OptTreeNode *otn, int protocol)
00103 {
00104 if(protocol != IPPROTO_TCP)
00105 {
00106 FatalError("%s(%d): Cannot check flow connection "
00107 "for non-TCP traffic\n", file_name, file_line);
00108 }
00109
00110
00111 if(otn->ds_list[PLUGIN_CLIENTSERVER])
00112 {
00113 FatalError("%s(%d): Multiple flow options in rule\n", file_name,
00114 file_line);
00115 }
00116
00117
00118 InitFlowData(otn);
00119 ParseFlowArgs(data, otn);
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 void ParseFlowArgs(char *data, OptTreeNode *otn)
00137 {
00138 char *token, *str, *p;
00139 ClientServerData *csd;
00140
00141 csd = (ClientServerData *)otn->ds_list[PLUGIN_CLIENTSERVER];
00142
00143 str = strdup(data);
00144
00145 if(str == NULL)
00146 {
00147 FatalError("ParseFlowArgs: Can't strdup data\n");
00148 }
00149
00150 p = str;
00151
00152
00153 while(isspace((int)*p)) p++;
00154
00155 token = strtok(p, ",");
00156
00157 while(token)
00158 {
00159 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
00160 "parsed %s,(%d)\n", token,strlen(token)););
00161
00162 while(isspace((int)*token))
00163 token++;
00164
00165 if(!strcasecmp(token, "to_server"))
00166 {
00167 csd->from_client = 1;
00168 }
00169 else if(!strcasecmp(token, "to_client"))
00170 {
00171 csd->from_server = 1;
00172 }
00173 else if(!strcasecmp(token, "from_server"))
00174 {
00175 csd->from_server = 1;
00176 }
00177 else if(!strcasecmp(token, "from_client"))
00178 {
00179 csd->from_client = 1;
00180 }
00181 else if(!strcasecmp(token, "stateless"))
00182 {
00183 otn->stateless = 1;
00184 }
00185 else if(!strcasecmp(token, "established"))
00186 {
00187 otn->established = 1;
00188 }
00189 else if(!strcasecmp(token, "not_established"))
00190 {
00191 otn->unestablished = 1;
00192 }
00193 else if(!strcasecmp(token, "no_stream"))
00194 {
00195 csd->ignore_reassembled = 1;
00196 }
00197 else if(!strcasecmp(token, "only_stream"))
00198 {
00199 csd->only_reassembled = 1;
00200 }
00201 else
00202 {
00203 FatalError("%s:%d: Unknown Flow Option: '%s'\n",
00204 file_name,file_line,token);
00205
00206 }
00207
00208
00209 token = strtok(NULL, ",");
00210 }
00211
00212 if(csd->from_client && csd->from_server)
00213 {
00214 FatalError("%s:%d: Can't use both from_client"
00215 "and flow_from server", file_name, file_line);
00216 }
00217
00218 if(csd->ignore_reassembled && csd->only_reassembled)
00219 {
00220 FatalError("%s:%d: Can't use no_stream and"
00221 " only_stream", file_name,file_line);
00222 }
00223
00224 if(otn->stateless && (csd->from_client || csd->from_server))
00225 {
00226 FatalError("%s:%d: Can't use flow: stateless option with"
00227 " other options", file_name, file_line);
00228 }
00229
00230 if(otn->stateless && otn->established)
00231 {
00232 FatalError("%s:%d: Can't specify established and stateless "
00233 "options in same rule\n", file_name, file_line);
00234 }
00235
00236 if(otn->stateless && otn->unestablished)
00237 {
00238 FatalError("%s:%d: Can't specify unestablished and stateless "
00239 "options in same rule\n", file_name, file_line);
00240 }
00241
00242 if(otn->established && otn->unestablished)
00243 {
00244 FatalError("%s:%d: Can't specify unestablished and established "
00245 "options in same rule\n", file_name, file_line);
00246 }
00247
00248 if(csd->from_client)
00249 {
00250 AddOptFuncToList(CheckFromClient, otn);
00251 }
00252
00253 if(csd->from_server)
00254 {
00255 AddOptFuncToList(CheckFromServer, otn);
00256 }
00257
00258 if(csd->ignore_reassembled)
00259 {
00260 AddOptFuncToList(CheckForNonReassembled, otn);
00261 }
00262
00263 if(csd->only_reassembled)
00264 {
00265 AddOptFuncToList(CheckForReassembled, otn);
00266 }
00267
00268
00269 free(str);
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 void InitFlowData(OptTreeNode * otn)
00284 {
00285
00286
00287
00288 otn->ds_list[PLUGIN_CLIENTSERVER] = (ClientServerData *)
00289 calloc(sizeof(ClientServerData), sizeof(char));
00290
00291 if(otn->ds_list[PLUGIN_CLIENTSERVER] == NULL)
00292 {
00293 FatalError("FlowData calloc Failed!\n");
00294 }
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 int CheckFromClient(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00311 {
00312 #ifdef DEBUG_CS
00313 DebugMessage(DEBUG_STREAM, "CheckFromClient: entering\n");
00314 if(p->packet_flags & PKT_REBUILT_STREAM)
00315 {
00316 DebugMessage(DEBUG_STREAM, "=> rebuilt!\n");
00317 }
00318 #endif
00319
00320 if(!pv.stateful)
00321 {
00322
00323 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00324 }
00325
00326 if(p->packet_flags & PKT_FROM_CLIENT ||
00327 !(p->packet_flags & PKT_FROM_SERVER))
00328 {
00329 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00330 }
00331
00332
00333 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "CheckFromClient: returning 0\n"););
00334 return 0;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 int CheckFromServer(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00352 {
00353 if(!pv.stateful)
00354 {
00355
00356 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00357 }
00358
00359 if(p->packet_flags & PKT_FROM_SERVER ||
00360 !(p->packet_flags & PKT_FROM_CLIENT))
00361 {
00362 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00363 }
00364
00365
00366 return 0;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 int CheckForReassembled(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00385 {
00386
00387 if(p->packet_flags & PKT_REBUILT_STREAM)
00388 {
00389 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00390 }
00391
00392
00393 return 0;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 int CheckForNonReassembled(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00411 {
00412
00413 if(p->packet_flags & PKT_REBUILT_STREAM)
00414 {
00415 return 0;
00416 }
00417
00418
00419 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00420 }