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
00031
00032
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <ctype.h>
00036 #include <sys/types.h>
00037
00038 #include "rules.h"
00039 #include "decode.h"
00040 #include "plugbase.h"
00041 #include "parser.h"
00042 #include "debug.h"
00043 #include "util.h"
00044 #include "plugin_enum.h"
00045 #include "snort.h"
00046 #include "flow.h"
00047 #include "bitop.h"
00048 #include "sfghash.h"
00049 #include "flow/flow.h"
00050 #include "spp_flow.h"
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 typedef struct _FLOWBITS_OBJECT
00063 {
00064 u_int32_t id;
00065 u_int8_t types;
00066 } FLOWBITS_OBJECT;
00067
00068
00069
00070
00071
00072
00073
00074 typedef struct _FLOWBITS_OP
00075 {
00076 u_int32_t id;
00077 u_int8_t type;
00078 } FLOWBITS_OP;
00079
00080 #define FLOWBITS_SET 0x01
00081 #define FLOWBITS_UNSET 0x02
00082 #define FLOWBITS_TOGGLE 0x04
00083 #define FLOWBITS_ISSET 0x08
00084 #define FLOWBITS_ISNOTSET 0x10
00085 #define FLOWBITS_RESET 0x20
00086 #define FLOWBITS_NOALERT 0x40
00087
00088 extern unsigned int giFlowbitSize;
00089
00090 static u_int32_t flowbits_count = 0;
00091 static SFGHASH *flowbits_hash;
00092
00093 static void FlowBitsInit(char *, OptTreeNode *, int);
00094 static void FlowBitsParse(char *, FLOWBITS_OP *, OptTreeNode *);
00095 static int FlowBitsCheck(Packet *, struct _OptTreeNode *, OptFpList *);
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 void SetupFlowBits()
00113 {
00114
00115 flowbits_hash = sfghash_new( 10000, 0 , 0, 0);
00116 if (!flowbits_hash) {
00117 FatalError("Could not setup flowbits hash\n");
00118 }
00119
00120
00121 RegisterPlugin("flowbits", FlowBitsInit);
00122
00123 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: FlowBits Setup\n"););
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 static void FlowBitsInit(char *data, OptTreeNode *otn, int protocol)
00140 {
00141 FLOWBITS_OP *flowbits;
00142 OptFpList *fpl;
00143
00144 if(!SppFlowIsRunning())
00145 {
00146 LogMessage("Warning: %s (%d) => flowbits without flow. flow must be enabled for this plugin.\n", file_name,file_line);
00147 }
00148
00149 flowbits = (FLOWBITS_OP *) SnortAlloc(sizeof(FLOWBITS_OP));
00150 if (!flowbits) {
00151 FatalError("%s (%d): Unable to allocate flowbits node\n", file_name,
00152 file_line);
00153 }
00154
00155 FlowBitsParse(data, flowbits, otn);
00156 fpl = AddOptFuncToList(FlowBitsCheck, otn);
00157
00158
00159
00160
00161
00162
00163 fpl->context = (void *) flowbits;
00164 return;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 static void FlowBitsParse(char *data, FLOWBITS_OP *flowbits, OptTreeNode *otn)
00181 {
00182 FLOWBITS_OBJECT *flowbits_item;
00183 char *token, *str, *p;
00184 u_int32_t id = 0;
00185 int hstatus;
00186
00187 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "flowbits parsing %s\n",data););
00188
00189 str = strdup(data);
00190
00191 if(str == NULL)
00192 {
00193 FatalError("ParseFlowArgs: Can't strdup data\n");
00194 }
00195
00196 p = str;
00197
00198
00199 while(isspace((int)*p)) p++;
00200
00201 token = strtok(p, ",");
00202 if(!token)
00203 {
00204 FatalError("%s(%d) ParseFlowArgs: Must specify flowbits operation.",
00205 file_name, file_line);
00206 }
00207
00208 while(isspace((int)*token))
00209 token++;
00210
00211 if(!strncasecmp("set",token,3))
00212 {
00213 flowbits->type = FLOWBITS_SET;
00214 }
00215 else if(!strncasecmp("unset",token,5))
00216 {
00217 flowbits->type = FLOWBITS_UNSET;
00218 }
00219 else if(!strncasecmp("toggle",token,6))
00220 {
00221 flowbits->type = FLOWBITS_TOGGLE;
00222 }
00223 else if(!strncasecmp("isset",token,5))
00224 {
00225 flowbits->type = FLOWBITS_ISSET;
00226 }
00227 else if(!strncasecmp("isnotset",token,8))
00228 {
00229 flowbits->type = FLOWBITS_ISNOTSET;
00230 }
00231 else if(!strncasecmp("noalert", token, 7))
00232 {
00233 if(strtok(NULL, " ,\t"))
00234 {
00235 FatalError("%s (%d): Do not specify a flowbits tag id for the "
00236 "keyword 'noalert'.\n", file_name, file_line);
00237 }
00238
00239 flowbits->type = FLOWBITS_NOALERT;
00240 flowbits->id = 0;
00241 free(str);
00242 return;
00243 }
00244 else if(!strncasecmp("reset",token,5))
00245 {
00246 if(strtok(NULL, " ,\t"))
00247 {
00248 FatalError("%s (%d): Do not specify a flowbits tag id for the "
00249 "keyword 'reset'.\n", file_name, file_line);
00250 }
00251
00252 flowbits->type = FLOWBITS_RESET;
00253 flowbits->id = 0;
00254 free(str);
00255 return;
00256 }
00257 else
00258 {
00259 FatalError("%s(%d) ParseFlowArgs: Invalid token %s\n",
00260 file_name, file_line, token);
00261 }
00262
00263
00264
00265
00266 token = strtok(NULL, " ,\t");
00267 if(!token || !strlen(token))
00268 {
00269 FatalError("%s (%d): flowbits tag id must be provided\n",
00270 file_name, file_line);
00271 }
00272
00273
00274
00275
00276 while(isspace((int)*token))
00277 token++;
00278
00279
00280
00281
00282 if (!strlen(token))
00283 {
00284 FatalError("%s (%d): flowbits tag id must be provided\n",
00285 file_name, file_line);
00286 }
00287
00288
00289
00290
00291 if(strtok(NULL, " ,\t"))
00292 {
00293 FatalError("%s (%d): flowbits tag id cannot include spaces or "
00294 "commas.\n", file_name, file_line);
00295 }
00296
00297 flowbits_item = (FLOWBITS_OBJECT *)sfghash_find(flowbits_hash, token);
00298
00299 if (flowbits_item)
00300 {
00301 flowbits_item->types |= flowbits->type;
00302 id = flowbits_item->id;
00303 }
00304 else
00305 {
00306 flowbits_item =
00307 (FLOWBITS_OBJECT *)SnortAlloc(sizeof(FLOWBITS_OBJECT));
00308
00309 flowbits_item->id = flowbits_count;
00310 flowbits_item->types |= flowbits->type;
00311
00312 hstatus = sfghash_add( flowbits_hash, token, flowbits_item);
00313 if(hstatus)
00314 {
00315 FatalError("Could not add flowbits key (%s) to hash",token);
00316 }
00317
00318 id = flowbits_count;
00319
00320 flowbits_count++;
00321
00322 if(flowbits_count >= (giFlowbitSize<<3) )
00323 {
00324 FatalError("FLOWBITS ERROR: The number of flowbit IDs in the "
00325 "current ruleset (%d) exceed the maximum number of IDs "
00326 "that are allowed (%d).\n", flowbits_count,giFlowbitSize<<3);
00327 }
00328 }
00329
00330 flowbits->id = id;
00331
00332 free(str);
00333 }
00334
00335 static int ResetFlowbits(Packet *p)
00336 {
00337 Session *ssn;
00338
00339 if(!p || !p->ssnptr)
00340 {
00341 return 0;
00342 }
00343
00344 ssn = p->ssnptr;
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 if((p->packet_flags & PKT_STREAM_EST) ||
00356 ((ssn->session_flags & (SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER)) ==
00357 (SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER)))
00358 {
00359 return 0;
00360 }
00361
00362 return 1;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 static FLOWDATA *GetFlowbitsData(Packet *p)
00374 {
00375 FLOW *fp;
00376 FLOWDATA *flowdata;
00377
00378 if(!p->flow)
00379 {
00380 return NULL;
00381 }
00382
00383 fp = (FLOW *)p->flow;
00384
00385 flowdata = &(fp->data);
00386 if(!flowdata)
00387 return NULL;
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 if(ResetFlowbits(p))
00399 {
00400 boResetBITOP(&(flowdata->boFlowbits));
00401 }
00402
00403 return flowdata;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 static int FlowBitsCheck(Packet *p,struct _OptTreeNode *otn, OptFpList *fp_list)
00419 {
00420 FLOWBITS_OP *flowbits;
00421 FLOWDATA *flowdata;
00422 int result = 0;
00423
00424 if(!p)
00425 {
00426 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,
00427 "FLOWBITSCHECK: No pkt."););
00428 return 0;
00429 }
00430
00431 flowdata = GetFlowbitsData(p);
00432 if(!flowdata)
00433 {
00434 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "No FLOWBITS_DATA"););
00435 return 0;
00436 }
00437
00438 flowbits = (FLOWBITS_OP *) fp_list->context;
00439
00440 DEBUG_WRAP
00441 (
00442 DebugMessage(DEBUG_PLUGIN,"flowbits: type = %d\n",flowbits->type);
00443 DebugMessage(DEBUG_PLUGIN,"flowbits: value = %d\n",flowbits->id);
00444 );
00445
00446 switch(flowbits->type)
00447 {
00448 case FLOWBITS_SET:
00449 boSetBit(&(flowdata->boFlowbits),flowbits->id);
00450 result = 1;
00451 break;
00452
00453 case FLOWBITS_UNSET:
00454 boClearBit(&(flowdata->boFlowbits),flowbits->id);
00455 result = 1;
00456 break;
00457
00458 case FLOWBITS_RESET:
00459 boResetBITOP(&(flowdata->boFlowbits));
00460 result = 1;
00461 break;
00462
00463 case FLOWBITS_ISSET:
00464 if(boIsBitSet(&(flowdata->boFlowbits),flowbits->id))
00465 {
00466 result = 1;
00467 }
00468 break;
00469
00470 case FLOWBITS_ISNOTSET:
00471 if (boIsBitSet(&(flowdata->boFlowbits),flowbits->id))
00472 {
00473 result = 0;
00474 }
00475 else
00476 {
00477 result = 1;
00478 }
00479 break;
00480
00481 case FLOWBITS_TOGGLE:
00482 if (boIsBitSet(&(flowdata->boFlowbits),flowbits->id))
00483 {
00484 boClearBit(&(flowdata->boFlowbits),flowbits->id);
00485 }
00486 else
00487 {
00488 boSetBit(&(flowdata->boFlowbits),flowbits->id);
00489 }
00490
00491 result = 1;
00492
00493 break;
00494
00495 case FLOWBITS_NOALERT:
00496
00497
00498
00499
00500
00501 fp_list->next->OptTestFunc(p, otn, fp_list->next);
00502 return 0;
00503
00504 default:
00505
00506
00507
00508 return 0;
00509 }
00510
00511
00512
00513
00514 if (result == 1)
00515 {
00516 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00517 }
00518
00519 return 0;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 void FlowBitsVerify(void)
00534 {
00535 SFGHASH_NODE * n;
00536 FLOWBITS_OBJECT *fb;
00537
00538 for (n = sfghash_findfirst(flowbits_hash);
00539 n != 0;
00540 n= sfghash_findnext(flowbits_hash))
00541 {
00542 fb = (FLOWBITS_OBJECT *)n->data;
00543
00544 if (fb->types & FLOWBITS_SET) {
00545 if (!(fb->types & FLOWBITS_ISSET || fb->types & FLOWBITS_ISNOTSET))
00546 {
00547 LogMessage("Warning: flowbits key '%s' is set but not ever checked.\n",n->key);
00548 }
00549 } else {
00550 if (fb->types & FLOWBITS_ISSET || fb->types & FLOWBITS_ISNOTSET) {
00551 LogMessage("Warning: flowbits key '%s' is checked but not ever set.\n",n->key);
00552 }
00553 }
00554 }
00555 }