00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #ifdef HAVE_STRINGS_H
00029 #include <strings.h>
00030 #endif
00031 #include <errno.h>
00032 #include <ctype.h>
00033 #ifndef WIN32
00034 #include <netdb.h>
00035 #include <sys/socket.h>
00036 #include <netinet/in.h>
00037 #include <arpa/inet.h>
00038 #include <grp.h>
00039 #include <pwd.h>
00040 #endif
00041 #include <unistd.h>
00042
00043 #include "src/preprocessors/flow/flow_print.h"
00044 #include "rules.h"
00045 #include "parser.h"
00046 #include "plugbase.h"
00047 #include "debug.h"
00048 #include "util.h"
00049 #include "mstring.h"
00050 #include "detect.h"
00051 #include "fpcreate.h"
00052 #include "log.h"
00053 #include "generators.h"
00054 #include "tag.h"
00055 #include "signature.h"
00056 #include "sfthreshold.h"
00057 #include "sfutil/sfthd.h"
00058 #include "snort.h"
00059 #include "inline.h"
00060 #include "event_queue.h"
00061 #include "asn1.h"
00062
00063 #define MAX_RULE_OPTIONS 256
00064 #define MAX_LINE_LENGTH 4096
00065
00066 ListHead Alert;
00067 ListHead Log;
00068 ListHead Pass;
00069 ListHead Activation;
00070 ListHead Dynamic;
00071 ListHead Drop;
00072 ListHead SDrop;
00073 ListHead Reject;
00074 ListHead RejectBoth;
00075 ListHead RejectSrc;
00076 ListHead RejectDst;
00077 ListHead Reinject;
00078
00079 RuleTreeNode *rtn_tmp;
00080 OptTreeNode *otn_tmp;
00081 ListHead *head_tmp = NULL;
00082
00083 RuleListNode *RuleLists;
00084
00085 struct VarEntry *VarHead = NULL;
00086
00087 char *file_name;
00088 int file_line;
00089
00090 int rule_count;
00091 int head_count;
00092 int opt_count;
00093
00094 int dynamic_rules_present;
00095 int active_dynamic_nodes;
00096
00097 extern unsigned int giFlowbitSize;
00098
00099 extern SNORT_EVENT_QUEUE g_event_queue;
00100
00101 extern KeywordXlateList *KeywordList;
00102 extern PreprocessKeywordList *PreprocessKeywords;
00103
00104 extern OutputFuncNode *AlertList;
00105 extern OutputFuncNode *LogList;
00106
00107 extern OutputFuncNode *DropList;
00108 #ifdef GIDS
00109 extern OutputFuncNode *SDropList;
00110 extern OutputFuncNode *RejectList;
00111 extern OutputFuncNode *RejectBothList;
00112 extern OutputFuncNode *RejectSrcList;
00113 extern OutputFuncNode *RejectDstList;
00114 #ifdef IPFW
00115 extern OutputFuncNode *ReinjectList;
00116 #endif
00117 #endif
00118
00119
00120 void ProcessHeadNode(RuleTreeNode *, ListHead *, int);
00121 void ParseSID(char *, OptTreeNode *);
00122 void ParseRev(char *, OptTreeNode *);
00123 void XferHeader(RuleTreeNode *, RuleTreeNode *);
00124 void DumpChain(RuleTreeNode *, char *, char *);
00125 void IntegrityCheck(RuleTreeNode *, char *, char *);
00126 void SetLinks(RuleTreeNode *, RuleTreeNode *);
00127 int ProcessIP(char *, RuleTreeNode *, int );
00128 IpAddrSet *AllocAddrNode(RuleTreeNode *, int );
00129 int TestHeader(RuleTreeNode *, RuleTreeNode *);
00130 RuleTreeNode *GetDynamicRTN(int, RuleTreeNode *);
00131 OptTreeNode *GetDynamicOTN(int, RuleTreeNode *);
00132 void AddrToFunc(RuleTreeNode *, int);
00133 void PortToFunc(RuleTreeNode *, int, int, int);
00134 void SetupRTNFuncList(RuleTreeNode *);
00135 static void ParsePortList(char *args);
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 void ParseRulesFile(char *file, int inclevel)
00152 {
00153 FILE *thefp;
00154 char buf[MAX_LINE_LENGTH+1];
00155 char *index;
00156 char *stored_file_name = file_name;
00157 int stored_file_line = file_line;
00158 char *saved_line = NULL;
00159 int continuation = 0;
00160 char *new_line = NULL;
00161 struct stat file_stat;
00162
00163 if(inclevel == 0)
00164 {
00165 if(!pv.quiet_flag)
00166 {
00167 LogMessage("\n+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
00168 LogMessage("Initializing rule chains...\n");
00169 }
00170 }
00171
00172 stored_file_line = file_line;
00173 stored_file_name = file_name;
00174 file_line = 0;
00175
00176
00177
00178
00179
00180
00181
00182 file_name = strdup(file);
00183 if(file_name == NULL)
00184 {
00185 FatalError("ParseRulesFile strdup failed: %s\n",
00186 strerror(errno));
00187 }
00188
00189
00190
00191
00192
00193 if(stat(file_name, &file_stat) < 0)
00194 {
00195 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"ParseRulesFile: stat "
00196 "on %s failed - going to config_dir\n", file_name););
00197
00198 free(file_name);
00199
00200 file_name = calloc(strlen(file) + strlen(pv.config_dir) + 1,
00201 sizeof(char));
00202
00203 if(file_name == NULL)
00204 {
00205 FatalError("ParseRulesFile calloc failed: %s\n",
00206 strerror(errno));
00207 }
00208
00209 strlcpy(file_name, pv.config_dir, strlen(file) +
00210 strlen(pv.config_dir) + 1);
00211
00212 strlcat(file_name, file, strlen(file) + strlen(pv.config_dir) + 1);
00213
00214 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"ParseRulesFile: Opening "
00215 "and parsing %s\n", file_name););
00216 }
00217
00218
00219 if((thefp = fopen(file_name, "r")) == NULL)
00220 {
00221 FatalError("Unable to open rules file: %s or %s\n", file,
00222 file_name);
00223 }
00224
00225
00226 bzero((char *) buf, MAX_LINE_LENGTH+1);
00227
00228
00229
00230 while((fgets(buf, MAX_LINE_LENGTH, thefp)) != NULL)
00231 {
00232
00233
00234
00235
00236 file_line++;
00237
00238 index = buf;
00239
00240 #ifdef DEBUG2
00241 LogMessage("Got line %s (%d): %s\n", file_name, file_line, buf);
00242 #endif
00243
00244 while(*index == ' ' || *index == '\t')
00245 index++;
00246
00247
00248 if((*index != '#') && (*index != 0x0a) && (*index != ';') &&
00249 (index != NULL))
00250 {
00251 if(continuation == 1)
00252 {
00253 new_line = (char *) calloc((strlen(saved_line) + strlen(index)
00254 +1), sizeof(char));
00255 strncat(new_line, saved_line, strlen(saved_line));
00256 strncat(new_line, index, strlen(index));
00257 free(saved_line);
00258 saved_line = NULL;
00259 index = new_line;
00260
00261 if(strlen(index) > PARSERULE_SIZE)
00262 {
00263 FatalError("Please don't try to overflow the parser, "
00264 "that's not very nice of you... (%d-byte "
00265 "limit on rule size)\n", PARSERULE_SIZE);
00266 }
00267
00268 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"concat rule: %s\n",
00269 new_line););
00270 }
00271
00272
00273
00274
00275 if(ContinuationCheck(index) == 0)
00276 {
00277 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
00278 "[*] Processing rule: %s\n", index););
00279
00280 ParseRule(thefp, index, inclevel);
00281
00282 if(new_line != NULL)
00283 {
00284 free(new_line);
00285 new_line = NULL;
00286 continuation = 0;
00287 }
00288 }
00289 else
00290 {
00291
00292 saved_line = strdup(index);
00293
00294
00295
00296
00297 continuation = 1;
00298 }
00299 }
00300
00301 bzero((char *) buf, MAX_LINE_LENGTH+1);
00302 }
00303
00304 if(file_name)
00305 free(file_name);
00306
00307 file_name = stored_file_name;
00308 file_line = stored_file_line;
00309
00310 if(inclevel == 0 && !pv.quiet_flag)
00311 {
00312 LogMessage("%d Snort rules read...\n", rule_count);
00313 LogMessage("%d Option Chains linked into %d Chain Headers\n", opt_count,
00314 head_count);
00315 LogMessage("%d Dynamic rules\n", dynamic_rules_present);
00316 LogMessage("+++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
00317 }
00318
00319 fclose(thefp);
00320
00321
00322 if(dynamic_rules_present)
00323 {
00324 LinkDynamicRules();
00325 }
00326
00327 if(inclevel == 0)
00328 {
00329 #ifdef DEBUG
00330 DumpRuleChains();
00331 #endif
00332
00333 IntegrityCheckRules();
00334
00335 }
00336
00337 return;
00338 }
00339
00340
00341
00342 int ContinuationCheck(char *rule)
00343 {
00344 char *idx;
00345
00346 idx = rule + strlen(rule) - 1;
00347
00348 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"initial idx set to \'%c\'\n",
00349 *idx););
00350
00351 while(isspace((int)*idx))
00352 {
00353 idx--;
00354 }
00355
00356 if(*idx == '\\')
00357 {
00358 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Got continuation char, "
00359 "clearing char and returning 1\n"););
00360
00361
00362 *idx = '\x0';
00363 return 1;
00364 }
00365
00366 return 0;
00367 }
00368
00369
00370 int CheckRule(char *str)
00371 {
00372 int len;
00373 int got_paren = 0;
00374 int got_semi = 0;
00375 char *index;
00376
00377 len = strlen(str);
00378
00379 index = str + len - 1;
00380
00381 while((isspace((int)*index)))
00382 {
00383 if(index > str)
00384 index--;
00385 else
00386 return 0;
00387 }
00388
00389
00390 if(*index == ')')
00391 {
00392 got_paren = 1;
00393 index--;
00394 }
00395
00396 while((isspace((int)*index)))
00397 {
00398 if(index > str)
00399 index--;
00400 else
00401 return 0;
00402 }
00403
00404
00405 if(*index == ';')
00406 {
00407 got_semi = 1;
00408 }
00409
00410 if(got_semi && got_paren)
00411 {
00412 return 1;
00413 }
00414 else
00415 {
00416
00417 for(index = str; index < str+len; index++)
00418 {
00419 if(*index == '(')
00420 {
00421 return 0;
00422 }
00423 }
00424
00425 return 1;
00426 }
00427
00428 }
00429
00430 void DumpRuleChains()
00431 {
00432 RuleListNode *rule;
00433
00434 rule = RuleLists;
00435
00436 while(rule != NULL)
00437 {
00438 DumpChain(rule->RuleList->IpList, rule->name, "IP Chains");
00439 DumpChain(rule->RuleList->TcpList, rule->name, "TCP Chains");
00440 DumpChain(rule->RuleList->UdpList, rule->name, "UDP Chains");
00441 DumpChain(rule->RuleList->IcmpList, rule->name, "ICMP Chains");
00442 rule = rule->next;
00443 }
00444 }
00445
00446 void IntegrityCheckRules()
00447 {
00448 RuleListNode *rule;
00449
00450 rule = RuleLists;
00451
00452 if(!pv.quiet_flag)
00453 {
00454 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Performing Rule "
00455 "List Integrity Tests...\n"););
00456 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"----------------"
00457 "-----------------------\n"););
00458 }
00459
00460 while(rule != NULL)
00461 {
00462 IntegrityCheck(rule->RuleList->IpList, rule->name, "IP Chains");
00463 IntegrityCheck(rule->RuleList->TcpList, rule->name, "TCP Chains");
00464 IntegrityCheck(rule->RuleList->UdpList, rule->name, "UDP Chains");
00465 IntegrityCheck(rule->RuleList->IcmpList, rule->name, "ICMP Chains");
00466 rule = rule->next;
00467 }
00468
00469 if(!pv.quiet_flag)
00470 {
00471 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
00472 "---------------------------------------\n\n"););
00473 }
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 void ParseRule(FILE *rule_file, char *prule, int inclevel)
00489 {
00490 char **toks;
00491 int num_toks;
00492 int rule_type;
00493 char rule[PARSERULE_SIZE];
00494 int protocol = 0;
00495 char *tmp;
00496 RuleTreeNode proto_node;
00497 RuleListNode *node = RuleLists;
00498
00499
00500 strip(prule);
00501
00502
00503 bzero((void *)rule, sizeof(rule));
00504
00505 strncpy(rule, ExpandVars(prule), PARSERULE_SIZE-1);
00506
00507
00508 toks = mSplit(rule, " ", 10, &num_toks, 0);
00509
00510
00511
00512 bzero((char *) &proto_node, sizeof(RuleTreeNode));
00513
00514 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"[*] Rule start\n"););
00515
00516
00517 rule_type = RuleType(toks[0]);
00518
00519 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule type: "););
00520
00521
00522 switch(rule_type)
00523 {
00524 case RULE_DROP:
00525 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Drop\n"););
00526
00527
00528
00529 if (!InlineMode())
00530 {
00531 return;
00532 }
00533 break;
00534
00535 #ifdef GIDS
00536 case RULE_SDROP:
00537 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"SDrop\n"););
00538
00539
00540
00541 if (!InlineMode())
00542 {
00543 return;
00544 }
00545 break;
00546
00547 case RULE_REJECT:
00548 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Reject\n"););
00549
00550
00551
00552 if (!InlineMode())
00553 {
00554 return;
00555 }
00556 break;
00557
00558 case RULE_REJECTBOTH:
00559 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"RejectBoth\n"););
00560
00561
00562
00563 if (!InlineMode())
00564 {
00565 return;
00566 }
00567 break;
00568
00569 case RULE_REJECTSRC:
00570 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"RejectSrc\n"););
00571
00572
00573
00574 if (!InlineMode())
00575 {
00576 return;
00577 }
00578 break;
00579
00580 case RULE_REJECTDST:
00581 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"RejectDst\n"););
00582
00583
00584
00585 if (!InlineMode())
00586 {
00587 return;
00588 }
00589 break;
00590
00591 #ifdef IPFW
00592 case RULE_REINJECT:
00593 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Reinject\n"););
00594
00595
00596
00597 if (!InlineMode())
00598 {
00599 return;
00600 }
00601 break;
00602 #endif
00603 #endif
00604
00605 case RULE_PASS:
00606 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Pass\n"););
00607 break;
00608
00609 case RULE_LOG:
00610 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Log\n"););
00611 break;
00612
00613 case RULE_ALERT:
00614 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Alert\n"););
00615 break;
00616
00617 case RULE_INCLUDE:
00618 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Include\n"););
00619 if(*toks[1] == '$')
00620 {
00621 if((tmp = VarGet(toks[1]+1)) == NULL)
00622 {
00623 FatalError("%s(%d) => Undefined variable %s\n",
00624 file_name, file_line, toks[1]);
00625 }
00626 }
00627 else
00628 {
00629 tmp = toks[1];
00630 }
00631
00632 ParseRulesFile(tmp, inclevel + 1);
00633 mSplitFree(&toks, num_toks);
00634 return;
00635
00636 case RULE_VAR:
00637 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Variable\n"););
00638 VarDefine(toks[1], toks[2]);
00639 mSplitFree(&toks, num_toks);
00640 return;
00641
00642 case RULE_PREPROCESS:
00643 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Preprocessor\n"););
00644 ParsePreprocessor(rule);
00645 mSplitFree(&toks, num_toks);
00646 return;
00647
00648 case RULE_OUTPUT:
00649 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Output Plugin\n"););
00650 ParseOutputPlugin(rule);
00651 mSplitFree(&toks, num_toks);
00652 return;
00653
00654 case RULE_ACTIVATE:
00655 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Activation rule\n"););
00656 break;
00657
00658 case RULE_DYNAMIC:
00659 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Dynamic rule\n"););
00660 break;
00661
00662 case RULE_CONFIG:
00663 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule file config\n"););
00664 ParseConfig(rule);
00665 mSplitFree(&toks, num_toks);
00666 return;
00667
00668 case RULE_DECLARE:
00669 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule type declaration\n"););
00670 ParseRuleTypeDeclaration(rule_file, rule);
00671 mSplitFree(&toks, num_toks);
00672 return;
00673
00674 case RULE_THRESHOLD:
00675 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Threshold\n"););
00676 ParseSFThreshold(rule_file, rule);
00677 mSplitFree(&toks, num_toks);
00678 return;
00679
00680 case RULE_SUPPRESS:
00681 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Suppress\n"););
00682 ParseSFSuppress(rule_file, rule);
00683 mSplitFree(&toks, num_toks);
00684 return;
00685
00686 case RULE_UNKNOWN:
00687 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Unknown rule type, might be declared\n"););
00688
00689
00690 while(node != NULL)
00691 {
00692 if(!strcasecmp(node->name, toks[0]))
00693 break;
00694 node = node->next;
00695 }
00696
00697 if(node == NULL)
00698 {
00699 FatalError("%s(%d) => Unknown rule type: %s\n",
00700 file_name, file_line, toks[0]);
00701 }
00702
00703 break;
00704
00705 default:
00706 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Invalid input: %s\n", prule););
00707 mSplitFree(&toks, num_toks);
00708 return;
00709 }
00710
00711 if(num_toks < 7)
00712 {
00713 FatalError("%s(%d): Bad rule in rules file\n", file_name, file_line);
00714 }
00715
00716 if(!CheckRule(prule))
00717 {
00718 FatalError("Unterminated rule in file %s, line %d\n"
00719 " (Snort rules must be contained on a single line or\n"
00720 " on multiple lines with a '\\' continuation character\n"
00721 " at the end of the line, make sure there are no\n"
00722 " carriage returns before the end of this line)\n",
00723 file_name, file_line);
00724 return;
00725 }
00726
00727 if (rule_type == RULE_UNKNOWN)
00728 proto_node.type = node->mode;
00729 else
00730 proto_node.type = rule_type;
00731
00732
00733 protocol = WhichProto(toks[1]);
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 ProcessIP(toks[2], &proto_node, SRC);
00754
00755
00756
00757
00758 if(!strcasecmp(toks[3], "->") ||
00759 !strcasecmp(toks[3], "<>"))
00760 {
00761 FatalError("%s:%d => Port value missing in rule!\n",
00762 file_name, file_line);
00763 }
00764
00765
00766 if(ParsePort(toks[3], (u_short *) & proto_node.hsp,
00767 (u_short *) & proto_node.lsp, toks[1],
00768 (int *) &proto_node.not_sp_flag))
00769 {
00770 proto_node.flags |= ANY_SRC_PORT;
00771 }
00772
00773 if(proto_node.not_sp_flag)
00774 proto_node.flags |= EXCEPT_SRC_PORT;
00775
00776
00777
00778
00779
00780
00781 if(!strncmp("<>", toks[4], 2))
00782 {
00783 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Bidirectional rule!\n"););
00784 proto_node.flags |= BIDIRECTIONAL;
00785 }
00786
00787
00788
00789
00790
00791 if(strcmp("->", toks[4]) && strcmp("<>", toks[4]))
00792 {
00793 FatalError("%s(%d): Illegal direction specifier: %s\n", file_name,
00794 file_line, toks[4]);
00795 }
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 ProcessIP(toks[5], &proto_node, DST);
00809
00810 if(ParsePort(toks[6], (u_short *) & proto_node.hdp,
00811 (u_short *) & proto_node.ldp, toks[1],
00812 (int *) &proto_node.not_dp_flag))
00813 {
00814 proto_node.flags |= ANY_DST_PORT;
00815 }
00816
00817
00818 if (num_toks > 7 && toks[7][0] != '(')
00819 {
00820 FatalError("%s(%d): The rule option section (starting with a '(') must "
00821 "follow immediately after the destination port. "
00822 "This means port lists are not supported.\n",
00823 file_name, file_line);
00824 }
00825
00826 if(proto_node.not_dp_flag)
00827 proto_node.flags |= EXCEPT_DST_PORT;
00828
00829 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"proto_node.flags = 0x%X\n", proto_node.flags););
00830 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Processing Head Node....\n"););
00831
00832 switch(rule_type)
00833 {
00834 case RULE_DROP:
00835 if (InlineMode())
00836 {
00837 ProcessHeadNode(&proto_node, &Drop, protocol);
00838 }
00839 break;
00840
00841 #ifdef GIDS
00842 case RULE_SDROP:
00843 if (InlineMode())
00844 {
00845 ProcessHeadNode(&proto_node, &SDrop, protocol);
00846 }
00847 break;
00848
00849 case RULE_REJECT:
00850 if (InlineMode())
00851 {
00852 ProcessHeadNode(&proto_node, &Reject, protocol);
00853 }
00854 break;
00855
00856 case RULE_REJECTBOTH:
00857 if (InlineMode())
00858 {
00859 ProcessHeadNode(&proto_node, &RejectBoth, protocol);
00860 }
00861 break;
00862
00863 case RULE_REJECTSRC:
00864 if (InlineMode())
00865 {
00866 ProcessHeadNode(&proto_node, &RejectSrc, protocol);
00867 }
00868 break;
00869
00870 case RULE_REJECTDST:
00871 if (InlineMode())
00872 {
00873 ProcessHeadNode(&proto_node, &RejectDst, protocol);
00874 }
00875 break;
00876
00877 #ifdef IPFW
00878 case RULE_REINJECT:
00879 if (InlineMode())
00880 {
00881 ProcessHeadNode(&proto_node, &Reinject, protocol);
00882 }
00883 break;
00884 #endif
00885 #endif
00886
00887 case RULE_ALERT:
00888 ProcessHeadNode(&proto_node, &Alert, protocol);
00889 break;
00890
00891 case RULE_LOG:
00892 ProcessHeadNode(&proto_node, &Log, protocol);
00893 break;
00894
00895 case RULE_PASS:
00896 ProcessHeadNode(&proto_node, &Pass, protocol);
00897 break;
00898
00899 case RULE_ACTIVATE:
00900 ProcessHeadNode(&proto_node, &Activation, protocol);
00901 break;
00902
00903 case RULE_DYNAMIC:
00904 ProcessHeadNode(&proto_node, &Dynamic, protocol);
00905 break;
00906
00907 case RULE_UNKNOWN:
00908 ProcessHeadNode(&proto_node, node->RuleList, protocol);
00909 break;
00910
00911 default:
00912 FatalError("Unable to determine rule type (%s) for processing, exiting!\n", toks[0]);
00913 }
00914
00915 rule_count++;
00916
00917 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Parsing Rule Options...\n"););
00918
00919 if (rule_type == RULE_UNKNOWN)
00920 ParseRuleOptions(rule, node->mode, protocol);
00921 else
00922 ParseRuleOptions(rule, rule_type, protocol);
00923
00924 mSplitFree(&toks, num_toks);
00925
00926 return;
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 void ProcessHeadNode(RuleTreeNode * test_node, ListHead * list, int protocol)
00944 {
00945 int match = 0;
00946 RuleTreeNode *rtn_idx;
00947 RuleTreeNode *rtn_prev;
00948 RuleTreeNode *rtn_head_ptr;
00949 int count = 0;
00950 int insert_complete = 0;
00951 #ifdef DEBUG
00952 int i;
00953 #endif
00954
00955
00956 switch(protocol)
00957 {
00958 case IPPROTO_TCP:
00959 rtn_idx = list->TcpList;
00960 break;
00961
00962 case IPPROTO_UDP:
00963 rtn_idx = list->UdpList;
00964 break;
00965
00966 case IPPROTO_ICMP:
00967 rtn_idx = list->IcmpList;
00968 break;
00969
00970 case ETHERNET_TYPE_IP:
00971 rtn_idx = list->IpList;
00972 break;
00973
00974 default:
00975 rtn_idx = NULL;
00976 break;
00977 }
00978
00979
00980
00981
00982
00983 rtn_head_ptr = rtn_idx;
00984
00985
00986
00987
00988
00989 if(rtn_idx == NULL)
00990 {
00991 head_count++;
00992
00993 switch(protocol)
00994 {
00995 case IPPROTO_TCP:
00996 list->TcpList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode),
00997 sizeof(char));
00998 rtn_tmp = list->TcpList;
00999 break;
01000
01001 case IPPROTO_UDP:
01002 list->UdpList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode),
01003 sizeof(char));
01004 rtn_tmp = list->UdpList;
01005 break;
01006
01007 case IPPROTO_ICMP:
01008 list->IcmpList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode),
01009 sizeof(char));
01010 rtn_tmp = list->IcmpList;
01011 break;
01012
01013 case ETHERNET_TYPE_IP:
01014 list->IpList = (RuleTreeNode *) calloc(sizeof(RuleTreeNode),
01015 sizeof(char));
01016 rtn_tmp = list->IpList;
01017 break;
01018
01019 }
01020
01021
01022 XferHeader(test_node, rtn_tmp);
01023
01024 rtn_tmp->head_node_number = head_count;
01025
01026
01027 rtn_tmp->down = NULL;
01028
01029
01030 SetupRTNFuncList(rtn_tmp);
01031
01032
01033 rtn_tmp->listhead = list;
01034
01035 return;
01036 }
01037
01038
01039 match = TestHeader(rtn_idx, test_node);
01040
01041 while((rtn_idx->right != NULL) && !match)
01042 {
01043 count++;
01044 match = TestHeader(rtn_idx, test_node);
01045
01046 if(!match)
01047 rtn_idx = rtn_idx->right;
01048 else
01049 break;
01050 }
01051
01052
01053
01054
01055
01056 match = TestHeader(rtn_idx, test_node);
01057
01058
01059
01060
01061
01062 if(!match)
01063 {
01064 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Building New Chain head node\n"););
01065
01066 head_count++;
01067
01068
01069
01070 rtn_tmp = (RuleTreeNode *) calloc(sizeof(RuleTreeNode),
01071 sizeof(char));
01072
01073
01074
01075
01076
01077 if(rtn_tmp == NULL)
01078 {
01079 FatalError("Unable to allocate Rule Head Node!!\n");
01080 }
01081
01082
01083 XferHeader(test_node, rtn_tmp);
01084
01085 rtn_tmp->head_node_number = head_count;
01086 rtn_tmp->down = NULL;
01087
01088
01089 SetupRTNFuncList(rtn_tmp);
01090
01091
01092 rtn_tmp->listhead = list;
01093
01094 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
01095 "New Chain head flags = 0x%X\n", rtn_tmp->flags););
01096
01097
01098 if(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
01099 {
01100
01101
01102
01103
01104 rtn_idx = rtn_head_ptr;
01105 rtn_prev = NULL;
01106 insert_complete = 0;
01107
01108
01109
01110
01111
01112
01113
01114 if(rtn_tmp->flags & EXCEPT_DST_PORT)
01115 {
01116 switch(protocol)
01117 {
01118 case IPPROTO_TCP:
01119 rtn_tmp->right = list->TcpList;
01120 list->TcpList = rtn_tmp;
01121 break;
01122
01123 case IPPROTO_UDP:
01124 rtn_tmp->right = list->UdpList;
01125 list->UdpList = rtn_tmp;
01126 break;
01127 }
01128
01129 rtn_head_ptr = rtn_tmp;
01130 insert_complete = 1;
01131 }
01132 else
01133 {
01134 while(rtn_idx != NULL)
01135 {
01136 if(rtn_idx->flags & EXCEPT_DST_PORT ||
01137 rtn_idx->ldp < rtn_tmp->ldp)
01138 {
01139 rtn_prev = rtn_idx;
01140 rtn_idx = rtn_idx->right;
01141 }
01142 else if(rtn_idx->ldp == rtn_tmp->ldp)
01143 {
01144 rtn_tmp->right = rtn_idx->right;
01145 rtn_idx->right = rtn_tmp;
01146 insert_complete = 1;
01147 break;
01148 }
01149 else
01150 {
01151 rtn_tmp->right = rtn_idx;
01152
01153 if(rtn_prev != NULL)
01154 {
01155 rtn_prev->right = rtn_tmp;
01156 }
01157 else
01158 {
01159 switch(protocol)
01160 {
01161 case IPPROTO_TCP:
01162 list->TcpList = rtn_tmp;
01163 break;
01164
01165 case IPPROTO_UDP:
01166 list->UdpList = rtn_tmp;
01167 break;
01168 }
01169
01170 rtn_head_ptr = rtn_tmp;
01171 }
01172
01173 insert_complete = 1;
01174
01175 break;
01176 }
01177 }
01178 }
01179
01180 if(!insert_complete)
01181 {
01182 rtn_prev->right = rtn_tmp;
01183 }
01184
01185 rtn_idx = rtn_head_ptr;
01186
01187 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
01188 "New %s node inserted, new order:\n",
01189 protocol == IPPROTO_TCP?"TCP":"UDP"););
01190
01191 #ifdef DEBUG
01192 i = 0;
01193
01194 while(rtn_idx != NULL)
01195 {
01196 if(rtn_idx->flags & EXCEPT_DST_PORT)
01197 {
01198 LogMessage("!");
01199 }
01200
01201 DebugMessage(DEBUG_CONFIGRULES, "%d ", rtn_idx->ldp);
01202 rtn_idx = rtn_idx->right;
01203 if(i++ == 10)
01204 {
01205 DebugMessage(DEBUG_CONFIGRULES, "\n");
01206 i = 0;
01207 }
01208 }
01209 DebugMessage(DEBUG_CONFIGRULES, "\n");
01210 #endif
01211 }
01212 else
01213 {
01214 rtn_idx->right = rtn_tmp;
01215 }
01216 }
01217 else
01218 {
01219 rtn_tmp = rtn_idx;
01220 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
01221 "Chain head %d flags = 0x%X\n", count, rtn_tmp->flags););
01222
01223 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
01224 "Adding options to chain head %d\n", count););
01225 }
01226 }
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 void AddRuleFuncToList(int (*func) (Packet *, struct _RuleTreeNode *, struct _RuleFpList *), RuleTreeNode * rtn)
01243 {
01244 RuleFpList *idx;
01245
01246 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding new rule to list\n"););
01247
01248 idx = rtn->rule_func;
01249
01250 if(idx == NULL)
01251 {
01252 rtn->rule_func = (RuleFpList *) calloc(sizeof(RuleFpList), sizeof(char));
01253
01254 rtn->rule_func->RuleHeadFunc = func;
01255 }
01256 else
01257 {
01258 while(idx->next != NULL)
01259 idx = idx->next;
01260
01261 idx->next = (RuleFpList *) calloc(sizeof(RuleFpList), sizeof(char));
01262
01263 idx = idx->next;
01264 idx->RuleHeadFunc = func;
01265 }
01266 }
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281 void SetupRTNFuncList(RuleTreeNode * rtn)
01282 {
01283 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Initializing RTN function list!\n"););
01284 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Functions: "););
01285
01286 if(rtn->flags & BIDIRECTIONAL)
01287 {
01288 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckBidirectional->\n"););
01289 AddRuleFuncToList(CheckBidirectional, rtn);
01290 }
01291 else
01292 {
01293
01294
01295
01296
01297
01298
01299 PortToFunc(rtn, (rtn->flags & ANY_DST_PORT ? 1 : 0),
01300 (rtn->flags & EXCEPT_DST_PORT ? 1 : 0), DST);
01301
01302
01303 PortToFunc(rtn, (rtn->flags & ANY_SRC_PORT ? 1 : 0),
01304 (rtn->flags & EXCEPT_SRC_PORT ? 1 : 0), SRC);
01305
01306
01307 AddrToFunc(rtn, SRC);
01308
01309
01310 AddrToFunc(rtn, DST);
01311 }
01312
01313 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"RuleListEnd\n"););
01314
01315
01316 AddRuleFuncToList(RuleListEnd, rtn);
01317 }
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339 void AddrToFunc(RuleTreeNode * rtn, int mode)
01340 {
01341
01342
01343
01344
01345 switch(mode)
01346 {
01347 case SRC:
01348 if((rtn->flags & ANY_SRC_IP) == 0)
01349 {
01350 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckSrcIP -> "););
01351 AddRuleFuncToList(CheckSrcIP, rtn);
01352 }
01353
01354 break;
01355
01356 case DST:
01357 if((rtn->flags & ANY_DST_IP) == 0)
01358 {
01359 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckDstIP -> "););
01360 AddRuleFuncToList(CheckDstIP, rtn);
01361 }
01362
01363 break;
01364 }
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 void PortToFunc(RuleTreeNode * rtn, int any_flag, int except_flag, int mode)
01385 {
01386
01387
01388
01389
01390 if(any_flag)
01391 return;
01392
01393
01394 if(except_flag)
01395 {
01396 switch(mode)
01397 {
01398 case SRC:
01399 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckSrcPortNotEq -> "););
01400 AddRuleFuncToList(CheckSrcPortNotEq, rtn);
01401 break;
01402
01403 case DST:
01404 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckDstPortNotEq -> "););
01405 AddRuleFuncToList(CheckDstPortNotEq, rtn);
01406 break;
01407 }
01408
01409 return;
01410 }
01411
01412 switch(mode)
01413 {
01414 case SRC:
01415 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckSrcPortEqual -> "););
01416 AddRuleFuncToList(CheckSrcPortEqual, rtn);
01417 break;
01418
01419 case DST:
01420 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"CheckDstPortEqual -> "););
01421 AddRuleFuncToList(CheckDstPortEqual, rtn);
01422 break;
01423 }
01424
01425 return;
01426 }
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445 void ParsePreprocessor(char *rule)
01446 {
01447 char **toks;
01448
01449 char **pp_head;
01450
01451 char *funcname;
01452 char *pp_args = NULL;
01453
01454 int num_arg_toks;
01455 int num_head_toks;
01456 int found = 0;
01457 PreprocessKeywordList *pl_idx;
01458
01459
01460
01461 toks = mSplit(rule, ":", 2, &num_arg_toks, '\\');
01462
01463 if(num_arg_toks > 1)
01464 {
01465
01466
01467
01468
01469 pp_args = toks[1];
01470 }
01471
01472
01473 pp_head = mSplit(toks[0], " ", 2, &num_head_toks, '\\');
01474
01475
01476 funcname = pp_head[1];
01477
01478
01479 pl_idx = PreprocessKeywords;
01480
01481
01482 while(pl_idx != NULL)
01483 {
01484 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
01485 "comparing: \"%s\" => \"%s\"\n",
01486 funcname, pl_idx->entry.keyword););
01487
01488 if(!strcasecmp(funcname, pl_idx->entry.keyword))
01489 {
01490 pl_idx->entry.func(pp_args);
01491 found = 1;
01492 }
01493 if(!found)
01494 {
01495 pl_idx = pl_idx->next;
01496 }
01497 else
01498 break;
01499 }
01500
01501 if(!found)
01502 {
01503 FatalError(" unknown preprocessor \"%s\"\n",
01504 funcname);
01505 }
01506
01507 mSplitFree(&toks, num_arg_toks);
01508 mSplitFree(&pp_head, num_head_toks);
01509 }
01510
01511
01512 void ParseOutputPlugin(char *rule)
01513 {
01514 char **toks;
01515 char **pp_head;
01516 char *plugin_name = NULL;
01517 char *pp_args = NULL;
01518 int num_arg_toks;
01519 int num_head_toks;
01520 OutputKeywordNode *plugin;
01521
01522 toks = mSplit(rule, ":", 2, &num_arg_toks, '\\');
01523
01524 if(num_arg_toks > 1)
01525 {
01526 pp_args = toks[1];
01527 }
01528 pp_head = mSplit(toks[0], " ", 2, &num_head_toks, '\\');
01529
01530 plugin_name = pp_head[1];
01531
01532 if(plugin_name == NULL)
01533 {
01534 FatalError("%s (%d): Output directive missing output plugin name!\n",
01535 file_name, file_line);
01536 }
01537
01538 plugin = GetOutputPlugin(plugin_name);
01539 if( plugin != NULL )
01540 {
01541 switch(plugin->node_type)
01542 {
01543 case NT_OUTPUT_SPECIAL:
01544 if(pv.alert_cmd_override)
01545 ErrorMessage("command line overrides rules file alert "
01546 "plugin!\n");
01547 if(pv.log_cmd_override)
01548 ErrorMessage("command line overrides rules file login "
01549 "plugin!\n");
01550 plugin->func(pp_args);
01551 break;
01552
01553 case NT_OUTPUT_ALERT:
01554 if(!pv.alert_cmd_override)
01555 {
01556
01557 plugin->func(pp_args);
01558 }
01559 else
01560 {
01561 ErrorMessage("command line overrides rules file alert "
01562 "plugin!\n");
01563 }
01564
01565 break;
01566
01567 case NT_OUTPUT_LOG:
01568 if(!pv.log_cmd_override)
01569 {
01570
01571 plugin->func(pp_args);
01572 }
01573 else
01574 {
01575 ErrorMessage("command line overrides rules file logging "
01576 "plugin!\n");
01577 }
01578
01579 break;
01580 }
01581
01582 }
01583
01584 mSplitFree(&toks, num_arg_toks);
01585 mSplitFree(&pp_head, num_head_toks);
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 void ParseRuleOptions(char *rule, int rule_type, int protocol)
01604 {
01605 char **toks = NULL;
01606 char **opts = NULL;
01607 char *idx;
01608 char *aux;
01609 int num_toks, original_num_toks=0;
01610 int i;
01611 int num_opts;
01612 int found = 0;
01613 OptTreeNode *otn_idx;
01614 KeywordXlateList *kw_idx;
01615 THDX_STRUCT thdx;
01616 int one_threshold = 0;
01617
01618
01619
01620 otn_idx = rtn_tmp->down;
01621
01622
01623
01624
01625
01626 if(otn_idx != NULL)
01627 {
01628
01629 while(otn_idx->next != NULL)
01630 {
01631 otn_idx = otn_idx->next;
01632 }
01633
01634
01635 otn_idx->next = (OptTreeNode *) calloc(sizeof(OptTreeNode),
01636 sizeof(char));
01637
01638
01639 otn_tmp = otn_idx->next;
01640
01641 if(otn_tmp == NULL)
01642 {
01643 FatalError("Unable to alloc OTN: %s", strerror(errno));
01644 }
01645
01646 otn_tmp->next = NULL;
01647 opt_count++;
01648
01649 }
01650 else
01651 {
01652
01653 otn_idx = (OptTreeNode *) calloc(sizeof(OptTreeNode), sizeof(char));
01654
01655 bzero((char *) otn_idx, sizeof(OptTreeNode));
01656
01657 otn_tmp = otn_idx;
01658
01659 if(otn_tmp == NULL)
01660 {
01661 FatalError("Unable to alloc OTN!\n");
01662 }
01663 otn_tmp->next = NULL;
01664 rtn_tmp->down = otn_tmp;
01665 opt_count++;
01666 }
01667
01668 otn_tmp->chain_node_number = opt_count;
01669 otn_tmp->type = rule_type;
01670 otn_tmp->proto_node = rtn_tmp;
01671 otn_tmp->event_data.sig_generator = GENERATOR_SNORT_ENGINE;
01672
01673
01674 otn_tmp->rtn = rtn_tmp;
01675
01676
01677 idx = index(rule, '(');
01678 i = 0;
01679
01680 if(idx != NULL)
01681 {
01682 int one_msg = 0;
01683 int one_logto = 0;
01684 int one_activates = 0;
01685 int one_activated_by = 0;
01686 int one_count = 0;
01687 int one_tag = 0;
01688 int one_sid = 0;
01689 int one_rev = 0;
01690 int one_priority = 0;
01691 int one_classtype = 0;
01692 int one_stateless = 0;
01693
01694 idx++;
01695
01696
01697 aux = strrchr(idx, ')');
01698
01699
01700 if(aux == NULL)
01701 {
01702 FatalError("%s(%d): Missing trailing ')' in rule: %s.\n",
01703 file_name, file_line, rule);
01704 }
01705 *aux = 0;
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 toks = mSplit(idx, ";", MAX_RULE_OPTIONS+1, &num_toks, '\\');
01716 if (num_toks > MAX_RULE_OPTIONS)
01717 {
01718
01719 FatalError("%s(%d): More than %d options in rule: %s.\n",
01720 file_name, file_line, MAX_RULE_OPTIONS, rule);
01721 }
01722 original_num_toks = num_toks;
01723
01724 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES," Got %d tokens\n", num_toks););
01725
01726 num_toks--;
01727
01728 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Parsing options list: "););
01729
01730
01731 while(num_toks)
01732 {
01733 char* option_name = NULL;
01734 char* option_args = NULL;
01735
01736 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES," option: %s\n", toks[i]););
01737
01738
01739 opts = mSplit(toks[i], ":", 4, &num_opts, '\\');
01740
01741
01742
01743 option_name = opts[0];
01744 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES," option name: %s\n", option_name););
01745 if (num_opts > 1)
01746 {
01747 option_args = opts[1];
01748 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES," option args: %s\n", option_args););
01749 }
01750
01751
01752 while(isspace((int) *option_name))
01753 option_name++;
01754
01755
01756 if(!strcasecmp(option_name, "msg"))
01757 {
01758 ONE_CHECK (one_msg, option_name);
01759 if(num_opts == 2)
01760 {
01761 ParseMessage(option_args);
01762 }
01763 else
01764 {
01765 FatalError("\n%s(%d) => No argument passed to "
01766 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01767 "or the argument to this keyword!\n", file_name,
01768 file_line, option_name);
01769 }
01770 }
01771 else if(!strcasecmp(option_name, "logto"))
01772 {
01773 ONE_CHECK (one_logto, option_name);
01774 if(num_opts == 2)
01775 {
01776 ParseLogto(option_args);
01777 }
01778 else
01779 {
01780 FatalError("\n%s(%d) => No argument passed to "
01781 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01782 "or the argument to this keyword!\n", file_name,
01783 file_line, option_name);
01784 }
01785 }
01786 else if(!strcasecmp(option_name, "activates"))
01787 {
01788 ONE_CHECK (one_activates, option_name);
01789 if(num_opts == 2)
01790 {
01791 ParseActivates(option_args);
01792 dynamic_rules_present++;
01793 }
01794 else
01795 {
01796 FatalError("\n%s(%d) => No argument passed to "
01797 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01798 "or the argument to this keyword!\n", file_name,
01799 file_line, option_name);
01800 }
01801 }
01802 else if(!strcasecmp(option_name, "activated_by"))
01803 {
01804 ONE_CHECK (one_activated_by, option_name);
01805 if(num_opts == 2)
01806 {
01807 ParseActivatedBy(option_args);
01808 dynamic_rules_present++;
01809 }
01810 else
01811 {
01812 FatalError("\n%s(%d) => No argument passed to "
01813 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01814 "or the argument to this keyword!\n", file_name,
01815 file_line, opts[0]);
01816 }
01817 }
01818 else if(!strcasecmp(option_name, "count"))
01819 {
01820 ONE_CHECK (one_count, option_name);
01821 if(num_opts == 2)
01822 {
01823 if(otn_tmp->type != RULE_DYNAMIC)
01824 FatalError("The \"count\" option may only be used with "
01825 "the dynamic rule type!\n");
01826 ParseCount(opts[1]);
01827 }
01828 else
01829 {
01830 FatalError("\n%s(%d) => No argument passed to "
01831 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01832 "or the argument to this keyword!\n", file_name,
01833 file_line, opts[0]);
01834 }
01835 }
01836 else if(!strcasecmp(option_name, "tag"))
01837 {
01838 ONE_CHECK (one_tag, opts[0]);
01839 if(num_opts == 2)
01840 {
01841 ParseTag(opts[1], otn_tmp);
01842 }
01843 else
01844 {
01845 FatalError("\n%s(%d) => No argument passed to "
01846 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01847 "or the argument to this keyword!\n", file_name,
01848 file_line, opts[0]);
01849 }
01850 }
01851 else if(!strcasecmp(option_name, "threshold"))
01852 {
01853 ONE_CHECK (one_threshold, opts[0]);
01854 if(num_opts == 2)
01855 {
01856 ParseThreshold2(&thdx, opts[1]);
01857 }
01858 else
01859 {
01860 FatalError("\n%s(%d) => No argument passed to "
01861 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01862 "or the argument to this keyword!\n", file_name,
01863 file_line, opts[0]);
01864 }
01865 }
01866 else if(!strcasecmp(option_name, "sid"))
01867 {
01868 ONE_CHECK (one_sid, opts[0]);
01869 if(num_opts == 2)
01870 {
01871 ParseSID(opts[1], otn_tmp);
01872 }
01873 else
01874 {
01875 FatalError("\n%s(%d) => No argument passed to "
01876 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01877 "or the argument to this keyword!\n", file_name,
01878 file_line, opts[0]);
01879 }
01880 }
01881 else if(!strcasecmp(option_name, "rev"))
01882 {
01883 ONE_CHECK (one_rev, opts[0]);
01884 if(num_opts == 2)
01885 {
01886 ParseRev(opts[1], otn_tmp);
01887 }
01888 else
01889 {
01890 FatalError("\n%s(%d) => No argument passed to "
01891 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01892 "or the argument to this keyword!\n", file_name,
01893 file_line, opts[0]);
01894 }
01895 }
01896 else if(!strcasecmp(option_name, "reference"))
01897 {
01898 if(num_opts == 2)
01899 {
01900 ParseReference(opts[1], otn_tmp);
01901 }
01902 else
01903 {
01904 FatalError("\n%s(%d) => No argument passed to "
01905 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01906 "or the argument to this keyword!\n", file_name,
01907 file_line, opts[0]);
01908 }
01909 }
01910 else if(!strcasecmp(option_name, "priority"))
01911 {
01912 ONE_CHECK (one_priority, opts[0]);
01913 if(num_opts == 2)
01914 {
01915 ParsePriority(opts[1], otn_tmp);
01916 }
01917 else
01918 {
01919 FatalError("\n%s(%d) => No argument passed to "
01920 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01921 "or the argument to this keyword!\n", file_name,
01922 file_line, opts[0]);
01923 }
01924 }
01925 else if(!strcasecmp(option_name, "classtype"))
01926 {
01927 ONE_CHECK (one_classtype, opts[0]);
01928 if(num_opts == 2)
01929 {
01930 ParseClassType(opts[1], otn_tmp);
01931 }
01932 else
01933 {
01934 FatalError("\n%s(%d) => No argument passed to "
01935 "keyword \"%s\"\nMake sure you didn't forget a ':' "
01936 "or the argument to this keyword!\n", file_name,
01937 file_line, option_name);
01938 }
01939 }
01940 else if(!strcasecmp(option_name, "stateless"))
01941 {
01942 ONE_CHECK (one_stateless, opts[0]);
01943 otn_tmp->stateless = 1;
01944 }
01945 else
01946 {
01947 kw_idx = KeywordList;
01948 found = 0;
01949
01950 while(kw_idx != NULL)
01951 {
01952 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "comparing: \"%s\" => \"%s\"\n",
01953 option_name, kw_idx->entry.keyword););
01954
01955 if(!strcasecmp(option_name, kw_idx->entry.keyword))
01956 {
01957 if(num_opts == 2)
01958 {
01959 kw_idx->entry.func(option_args, otn_tmp, protocol);
01960 }
01961 else
01962 {
01963 kw_idx->entry.func(NULL, otn_tmp, protocol);
01964 }
01965 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "%s->", kw_idx->entry.keyword););
01966 found = 1;
01967 break;
01968 }
01969 kw_idx = kw_idx->next;
01970 }
01971
01972 if(!found)
01973 {
01974
01975 FatalError("Warning: %s(%d) => Unknown keyword '%s' in "
01976 "rule!\n", file_name, file_line, opts[0]);
01977 }
01978 }
01979
01980 mSplitFree(&opts,num_opts);
01981
01982 --num_toks;
01983 i++;
01984 }
01985
01986 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"OptListEnd\n"););
01987 AddOptFuncToList(OptListEnd, otn_tmp);
01988 }
01989 else
01990 {
01991 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"OptListEnd\n"););
01992 AddOptFuncToList(OptListEnd, otn_tmp);
01993 }
01994
01995 if( one_threshold )
01996 {
01997 int rstat;
01998 thdx.sig_id = otn_tmp->sigInfo.id;
01999 thdx.gen_id = GENERATOR_SNORT_ENGINE;
02000 if( (rstat=sfthreshold_create( &thdx )) )
02001 {
02002 if( rstat == THD_TOO_MANY_THDOBJ )
02003 {
02004 FatalError("Rule-Threshold-Parse: could not create a threshold object -- only one per sid, sid = %u\n",thdx.sig_id);
02005 }
02006 else
02007 {
02008 FatalError("Unable to add Threshold object for Rule-sid = %u\n",thdx.sig_id);
02009 }
02010 }
02011 }
02012
02013 if(idx != NULL)
02014 mSplitFree(&toks,original_num_toks);
02015 }
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030 int RuleType(char *func)
02031 {
02032 if(func == NULL)
02033 {
02034 FatalError("%s(%d) => NULL rule type\n", file_name, file_line);
02035 }
02036
02037 if (!strcasecmp(func, "drop"))
02038 return RULE_DROP;
02039
02040 #ifdef GIDS
02041 if (!strcasecmp(func, "sdrop"))
02042 return RULE_SDROP;
02043
02044 if (!strcasecmp(func, "reject"))
02045 return RULE_REJECT;
02046
02047 if (!strcasecmp(func, "rejectboth"))
02048 return RULE_REJECTBOTH;
02049
02050 if (!strcasecmp(func, "rejectsrc"))
02051 return RULE_REJECTSRC;
02052
02053 if (!strcasecmp(func, "rejectdst"))
02054 return RULE_REJECTDST;
02055
02056 #ifdef IPFW
02057 if (!strcasecmp(func, "reinject"))
02058 return RULE_REINJECT;
02059 #endif
02060 #endif
02061
02062 if(!strcasecmp(func, "log"))
02063 return RULE_LOG;
02064
02065 if(!strcasecmp(func, "alert"))
02066 return RULE_ALERT;
02067
02068 if(!strcasecmp(func, "pass"))
02069 return RULE_PASS;
02070
02071 if(!strcasecmp(func, "var"))
02072 return RULE_VAR;
02073
02074 if(!strcasecmp(func, "include"))
02075 return RULE_INCLUDE;
02076
02077 if(!strcasecmp(func, "preprocessor"))
02078 return RULE_PREPROCESS;
02079
02080 if(!strcasecmp(func, "output"))
02081 return RULE_OUTPUT;
02082
02083 if(!strcasecmp(func, "activate"))
02084 return RULE_ACTIVATE;
02085
02086 if(!strcasecmp(func, "dynamic"))
02087 return RULE_DYNAMIC;
02088
02089 if(!strcasecmp(func, "config"))
02090 return RULE_CONFIG;
02091
02092 if(!strcasecmp(func, "ruletype"))
02093 return RULE_DECLARE;
02094
02095 if(!strcasecmp(func, "threshold"))
02096 return RULE_THRESHOLD;
02097
02098 if(!strcasecmp(func, "suppress"))
02099 return RULE_SUPPRESS;
02100
02101 return RULE_UNKNOWN;
02102 }
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117 int WhichProto(char *proto_str)
02118 {
02119 if(!strcasecmp(proto_str, "tcp"))
02120 return IPPROTO_TCP;
02121
02122 if(!strcasecmp(proto_str, "udp"))
02123 return IPPROTO_UDP;
02124
02125 if(!strcasecmp(proto_str, "icmp"))
02126 return IPPROTO_ICMP;
02127
02128 if(!strcasecmp(proto_str, "ip"))
02129 return ETHERNET_TYPE_IP;
02130
02131 if(!strcasecmp(proto_str, "arp"))
02132 return ETHERNET_TYPE_ARP;
02133
02134
02135
02136
02137
02138 FatalError("%s(%d) => Bad protocol: %s\n", file_name, file_line, proto_str);
02139
02140 return 0;
02141 }
02142
02143
02144
02145 int ProcessIP(char *addr, RuleTreeNode *rtn, int mode)
02146 {
02147 char **toks = NULL;
02148 int num_toks;
02149 int i;
02150 IpAddrSet *tmp_addr;
02151 char *tmp;
02152 char *enbracket;
02153
02154 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Got address string: %s\n",
02155 addr););
02156
02157 if(*addr == '!')
02158 {
02159 switch(mode)
02160 {
02161 case SRC:
02162 rtn->flags |= EXCEPT_SRC_IP;
02163 break;
02164
02165 case DST:
02166 rtn->flags |= EXCEPT_DST_IP;
02167 break;
02168 }
02169
02170 addr++;
02171 }
02172
02173 if(*addr == '$')
02174 {
02175 if((tmp = VarGet(addr + 1)) == NULL)
02176 {
02177 FatalError("%s(%d) => Undefined variable %s\n", file_name,
02178 file_line, addr);
02179 }
02180 }
02181 else
02182 {
02183 tmp = addr;
02184 }
02185
02186
02187
02188
02189 if(*tmp == '[')
02190 {
02191 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Found IP list!\n"););
02192
02193
02194 enbracket = strrchr(tmp, (int)']');
02195 if(enbracket)
02196 *enbracket = '\x0';
02197 else
02198 FatalError("%s(%d) => Unterminated IP List\n", file_name, file_line);
02199
02200 toks = mSplit(tmp+1, ",", 128, &num_toks, 0);
02201
02202 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"mSplit got %d tokens...\n",
02203 num_toks););
02204
02205 for(i=0; i< num_toks; i++)
02206 {
02207 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"adding %s to IP "
02208 "address list\n", toks[i]););
02209 tmp = toks[i];
02210 while (isspace((int)*tmp)||*tmp=='[') tmp++;
02211 enbracket = strrchr(tmp, (int)']');
02212 if(enbracket)
02213 *enbracket = '\x0';
02214
02215 if (strlen(tmp) == 0)
02216 continue;
02217
02218 tmp_addr = AllocAddrNode(rtn, mode);
02219 ParseIP(tmp, tmp_addr);
02220 if(tmp_addr->ip_addr == 0 && tmp_addr->netmask == 0)
02221 {
02222 switch(mode)
02223 {
02224 case SRC:
02225 rtn->flags |= ANY_SRC_IP;
02226 break;
02227
02228 case DST:
02229 rtn->flags |= ANY_DST_IP;
02230 break;
02231 }
02232 }
02233 }
02234
02235 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "Freeing %d tokens...\n",
02236 num_toks););
02237
02238 mSplitFree(&toks, num_toks);
02239 }
02240 else
02241 {
02242 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
02243 "regular IP address, processing...\n"););
02244 tmp_addr = AllocAddrNode(rtn, mode);
02245 ParseIP(tmp, tmp_addr);
02246 if(tmp_addr->ip_addr == 0 && tmp_addr->netmask == 0)
02247 {
02248 switch(mode)
02249 {
02250 case SRC:
02251 rtn->flags |= ANY_SRC_IP;
02252 break;
02253
02254 case DST:
02255 rtn->flags |= ANY_DST_IP;
02256 break;
02257 }
02258 }
02259 }
02260
02261 return 0;
02262 }
02263
02264
02265
02266 IpAddrSet *AllocAddrNode(RuleTreeNode *rtn, int mode)
02267 {
02268 IpAddrSet *idx;
02269
02270 switch(mode)
02271 {
02272 case SRC:
02273 if(rtn->sip == NULL)
02274 {
02275 rtn->sip = (IpAddrSet *)calloc(sizeof(IpAddrSet), sizeof(char));
02276 if(rtn->sip == NULL)
02277 {
02278 FatalError(" Unable to allocate node for IP list\n");
02279 }
02280 return rtn->sip;
02281 }
02282 else
02283 {
02284 idx = rtn->sip;
02285
02286 while(idx->next != NULL)
02287 {
02288 idx = idx->next;
02289 }
02290
02291 idx->next = (IpAddrSet *)calloc(sizeof(IpAddrSet), sizeof(char));
02292 if(idx->next == NULL)
02293 {
02294 FatalError(" Unable to allocate node for IP list\n");
02295 }
02296 return idx->next;
02297 }
02298
02299
02300 case DST:
02301 if(rtn->dip == NULL)
02302 {
02303 rtn->dip = (IpAddrSet *)calloc(sizeof(IpAddrSet), sizeof(char));
02304 if(rtn->dip == NULL)
02305 {
02306 FatalError(" Unable to allocate node for IP list\n");
02307 }
02308 return rtn->dip;
02309 }
02310 else
02311 {
02312 idx = rtn->dip;
02313
02314 while(idx->next)
02315 {
02316 idx = idx->next;
02317 }
02318
02319 idx->next = (IpAddrSet *)calloc(sizeof(IpAddrSet), sizeof(char));
02320 if(idx->next == NULL)
02321 {
02322 FatalError(" Unable to allocate node for IP list\n");
02323 }
02324 return idx->next;
02325 }
02326 }
02327
02328 return NULL;
02329 }
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343 int ParsePort(char *prule_port, u_short * hi_port, u_short * lo_port, char *proto, int *not_flag)
02344 {
02345 char **toks;
02346 int num_toks;
02347 char *rule_port;
02348
02349 *not_flag = 0;
02350
02351
02352 if(!strncmp(prule_port, "$", 1))
02353 {
02354 if((rule_port = VarGet(prule_port + 1)) == NULL)
02355 {
02356 FatalError("%s(%d) => Undefined variable %s\n", file_name, file_line, prule_port);
02357 }
02358 }
02359 else
02360 rule_port = prule_port;
02361
02362 if(rule_port[0] == '(')
02363 {
02364
02365 FatalError("%s(%d) => Bad port number: \"%s\"\n",
02366 file_name, file_line, rule_port);
02367 }
02368
02369
02370
02371 if(!strcasecmp(rule_port, "any"))
02372 {
02373 *hi_port = 0;
02374 *lo_port = 0;
02375 return 1;
02376 }
02377
02378 if(rule_port[0] == '!')
02379 {
02380 *not_flag = 1;
02381 rule_port++;
02382 }
02383
02384 if(rule_port[0] == ':')
02385 {
02386 *lo_port = 0;
02387 }
02388
02389 toks = mSplit(rule_port, ":", 2, &num_toks, 0);
02390
02391 switch(num_toks)
02392 {
02393 case 1:
02394 *hi_port = ConvPort(toks[0], proto);
02395
02396 if(rule_port[0] == ':')
02397 {
02398 *lo_port = 0;
02399 }
02400 else
02401 {
02402 *lo_port = *hi_port;
02403
02404 if(index(rule_port, ':') != NULL)
02405 {
02406 *hi_port = 65535;
02407 }
02408 }
02409
02410 break;
02411
02412 case 2:
02413 *lo_port = ConvPort(toks[0], proto);
02414
02415 if(toks[1][0] == 0)
02416 *hi_port = 65535;
02417 else
02418 *hi_port = ConvPort(toks[1], proto);
02419
02420 break;
02421
02422 default:
02423 FatalError("%s(%d) => port conversion failed on \"%s\"\n",
02424 file_name, file_line, rule_port);
02425 }
02426
02427 mSplitFree(&toks, num_toks);
02428
02429 return 0;
02430 }
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445 int ConvPort(char *port, char *proto)
02446 {
02447 int conv;
02448 char *digit;
02449 struct servent *service_info;
02450
02451
02452
02453
02454
02455 if(isalpha((int) port[0]) != 0)
02456 {
02457 service_info = getservbyname(port, proto);
02458
02459 if(service_info != NULL)
02460 {
02461 conv = ntohs(service_info->s_port);
02462 return conv;
02463 }
02464 else
02465 {
02466 FatalError("%s(%d) => getservbyname() failed on \"%s\"\n",
02467 file_name, file_line, port);
02468 }
02469 }
02470 digit = port;
02471 while (*digit) {
02472
02473 if(!isdigit((int) *digit))
02474 {
02475 FatalError("%s(%d) => Invalid port: %s\n", file_name,
02476 file_line, port);
02477 }
02478 digit++;
02479 }
02480
02481 conv = atoi(port);
02482
02483
02484 if((conv >= 0) && (conv < 65536))
02485 {
02486 return conv;
02487 }
02488 else
02489 {
02490 FatalError("%s(%d) => bad port number: %s\n", file_name,
02491 file_line, port);
02492 }
02493
02494 return 0;
02495 }
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510 void ParseMessage(char *msg)
02511 {
02512 char *ptr;
02513 char *end;
02514 int size;
02515 int count = 0;
02516 char *read;
02517 char *write;
02518
02519
02520 ptr = index(msg, '"');
02521
02522 if(ptr == NULL)
02523 {
02524 ptr = msg;
02525 }
02526 else
02527 ptr++;
02528
02529 end = index(ptr, '"');
02530
02531 if(end != NULL)
02532 *end = 0;
02533
02534 while(isspace((int) *ptr))
02535 ptr++;
02536
02537
02538 read = write = ptr;
02539
02540 while(read < end)
02541 {
02542 if(*read == '\\')
02543 {
02544 read++;
02545 count++;
02546
02547 if(read >= end)
02548 {
02549 break;
02550 }
02551 }
02552
02553 *write++ = *read++;
02554 }
02555
02556 if(end)
02557 {
02558 *(end - count) = '\x0';
02559 }
02560
02561
02562 size = strlen(msg) + 1;
02563 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "Message: %s\n", msg););
02564
02565
02566 if(size > 0)
02567 {
02568 otn_tmp->sigInfo.message = strdup(ptr);
02569
02570 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "Rule message set to: %s\n",
02571 otn_tmp->sigInfo.message););
02572
02573 }
02574 else
02575 {
02576 ErrorMessage("%s(%d): bad alert message size %d\n", file_name,
02577 file_line, size);
02578 }
02579
02580 return;
02581 }
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596 void ParseLogto(char *filename)
02597 {
02598 char *sptr;
02599 char *eptr;
02600
02601
02602 sptr = index(filename, '"');
02603 eptr = strrchr(filename, '"');
02604
02605 if(sptr != NULL && eptr != NULL)
02606 {
02607
02608 sptr++;
02609
02610
02611 *eptr = 0;
02612 }
02613 else
02614 {
02615 sptr = filename;
02616 }
02617
02618
02619 otn_tmp->logto = (char *) calloc(strlen(sptr) + 1, sizeof(char));
02620
02621 bzero((char *) otn_tmp->logto, strlen(sptr) + 1);
02622
02623 strncpy(otn_tmp->logto, sptr, strlen(sptr)+1);
02624
02625 return;
02626 }
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642 void ParseActivates(char *act_num)
02643 {
02644
02645
02646
02647
02648 while(!isdigit((int) *act_num))
02649 act_num++;
02650
02651 otn_tmp->activates = atoi(act_num);
02652
02653 return;
02654 }
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670 void ParseActivatedBy(char *act_by)
02671 {
02672 ActivateList *al_ptr;
02673
02674 al_ptr = rtn_tmp->activate_list;
02675
02676 if(al_ptr == NULL)
02677 {
02678 rtn_tmp->activate_list = (ActivateList *) calloc(sizeof(ActivateList), sizeof(char));
02679
02680 if(rtn_tmp->activate_list == NULL)
02681 {
02682 FatalError("ParseActivatedBy() calloc failed: %s\n", strerror(errno));
02683 }
02684
02685 al_ptr = rtn_tmp->activate_list;
02686 }
02687 else
02688 {
02689 while(al_ptr->next != NULL)
02690 {
02691 al_ptr = al_ptr->next;
02692 }
02693
02694 al_ptr->next = (ActivateList *) calloc(sizeof(ActivateList), sizeof(char));
02695
02696 al_ptr = al_ptr->next;
02697
02698 if(al_ptr == NULL)
02699 {
02700 FatalError("ParseActivatedBy() calloc failed: %s\n", strerror(errno));
02701 }
02702 }
02703
02704
02705 while(!isdigit((int) *act_by))
02706 act_by++;
02707
02708
02709 al_ptr->activated_by = atoi(act_by);
02710
02711
02712 otn_tmp->activated_by = atoi(act_by);
02713
02714 return;
02715 }
02716
02717
02718
02719 void ParseCount(char *num)
02720 {
02721 while(!isdigit((int) *num))
02722 num++;
02723
02724 otn_tmp->activation_counter = atoi(num);
02725
02726 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Set activation counter to %d\n", otn_tmp->activation_counter););
02727
02728 return;
02729 }
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746 void XferHeader(RuleTreeNode * rule, RuleTreeNode * rtn)
02747 {
02748 rtn->type = rule->type;
02749 rtn->sip = rule->sip;
02750 rtn->dip = rule->dip;
02751 rtn->hsp = rule->hsp;
02752 rtn->lsp = rule->lsp;
02753 rtn->hdp = rule->hdp;
02754 rtn->ldp = rule->ldp;
02755 rtn->flags = rule->flags;
02756 rtn->not_sp_flag = rule->not_sp_flag;
02757 rtn->not_dp_flag = rule->not_dp_flag;
02758 }
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774 int TestHeader(RuleTreeNode * rule, RuleTreeNode * rtn)
02775 {
02776 IpAddrSet *rule_idx;
02777 IpAddrSet *rtn_idx;
02778
02779 rtn_idx = rtn->sip;
02780 for(rule_idx = rule->sip; rule_idx != NULL; rule_idx = rule_idx->next)
02781 {
02782 if(rtn_idx && (rtn_idx->ip_addr == rule_idx->ip_addr) &&
02783 (rtn_idx->netmask == rule_idx->netmask) &&
02784 (rtn_idx->addr_flags == rule_idx->addr_flags))
02785 {
02786 rtn_idx = rtn_idx->next;
02787 }
02788 else
02789 {
02790 return 0;
02791 }
02792 }
02793
02794 rtn_idx = rtn->dip;
02795 for(rule_idx = rule->dip ; rule_idx != NULL; rule_idx = rule_idx->next)
02796 {
02797 if(rtn_idx && (rtn_idx->ip_addr == rule_idx->ip_addr) &&
02798 (rtn_idx->netmask == rule_idx->netmask) &&
02799 (rtn_idx->addr_flags == rule_idx->addr_flags))
02800 {
02801 rtn_idx = rtn_idx->next;
02802 }
02803 else
02804 {
02805 return 0;
02806 }
02807 }
02808
02809 if(rtn->hsp == rule->hsp)
02810 {
02811 if(rtn->lsp == rule->lsp)
02812 {
02813 if(rtn->hdp == rule->hdp)
02814 {
02815 if(rtn->ldp == rule->ldp)
02816 {
02817 if(rtn->flags == rule->flags)
02818 {
02819 return 1;
02820 }
02821 }
02822 }
02823 }
02824 }
02825 return 0;
02826 }
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840 struct VarEntry *VarAlloc()
02841 {
02842 struct VarEntry *new;
02843
02844 if((new = (struct VarEntry *) calloc(sizeof(struct VarEntry), sizeof(char))) == NULL)
02845 {
02846 FatalError("cannot allocate memory for VarEntry.");
02847 }
02848
02849 return(new);
02850 }
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864 struct VarEntry *VarDefine(char *name, char *value)
02865 {
02866 struct VarEntry *p;
02867
02868 if(value == NULL)
02869 {
02870 FatalError("%s(%d): Bad value in variable definition!\n"
02871 "Make sure you don't have a \"$\" in the var name\n",
02872 file_name, file_line);
02873 }
02874
02875 if(!VarHead)
02876 {
02877 p = VarAlloc();
02878 p->name = strdup(name);
02879 p->value = strdup(value);
02880 p->prev = p;
02881 p->next = p;
02882
02883 VarHead = p;
02884
02885 return p;
02886 }
02887 p = VarHead;
02888
02889 do
02890 {
02891 if(strcasecmp(p->name, name) == 0)
02892 {
02893 if (!(p->flags & VAR_STATIC))
02894 {
02895 if( p->value )
02896 free(p->value);
02897
02898 p->value = strdup(value);
02899 }
02900 return (p);
02901 }
02902 p = p->next;
02903
02904 } while(p != VarHead);
02905
02906 p = VarAlloc();
02907 p->name = strdup(name);
02908 p->value = strdup(value);
02909 p->prev = VarHead;
02910 p->next = VarHead->next;
02911 p->next->prev = p;
02912 VarHead->next = p;
02913
02914 return p;
02915 }
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929 void VarDelete(char *name)
02930 {
02931 struct VarEntry *p;
02932
02933
02934 if(!VarHead)
02935 return;
02936
02937 p = VarHead;
02938
02939 do
02940 {
02941 if(strcasecmp(p->name, name) == 0)
02942 {
02943 p->prev->next = p->next;
02944 p->next->prev = p->prev;
02945
02946 if(VarHead == p)
02947 if((VarHead = p->next) == p)
02948 VarHead = NULL;
02949
02950 if(p->name)
02951 free(p->name);
02952
02953 if(p->value)
02954 free(p->value);
02955
02956 free(p);
02957
02958 return;
02959 }
02960 p = p->next;
02961
02962 } while(p != VarHead);
02963 }
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978 char *VarGet(char *name)
02979 {
02980 struct VarEntry *p;
02981
02982
02983 if(VarHead)
02984 {
02985 p = VarHead;
02986
02987 do
02988 {
02989 if(strcasecmp(p->name, name) == 0)
02990 return(p->value);
02991
02992 p = p->next;
02993
02994 } while(p != VarHead);
02995 }
02996
02997 FatalError("Undefined variable name: (%s:%d): %s\n",
02998 file_name, file_line, name);
02999
03000
03001 return NULL;
03002 }
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015 char *ExpandVars(char *string)
03016 {
03017 static char estring[PARSERULE_SIZE];
03018 char rawvarname[128], varname[128], varaux[128], varbuffer[128], varmodifier, *varcontents;
03019 int varname_completed, c, i, j, iv, jv, l_string, name_only;
03020 int quote_toggle = 0;
03021
03022 if(!string || !*string || !strchr(string, '$'))
03023 return(string);
03024
03025 bzero((char *) estring, sizeof(estring));
03026
03027 i = j = 0;
03028 l_string = strlen(string);
03029 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "ExpandVars, Before: %s\n", string););
03030
03031 while(i < l_string && j < sizeof(estring) - 1)
03032 {
03033 c = string[i++];
03034
03035 if(c == '"')
03036 {
03037
03038
03039 quote_toggle ^= 1;
03040 }
03041
03042 if(c == '$' && !quote_toggle)
03043 {
03044 bzero((char *) rawvarname, sizeof(rawvarname));
03045 varname_completed = 0;
03046 name_only = 1;
03047 iv = i;
03048 jv = 0;
03049
03050 if(string[i] == '(')
03051 {
03052 name_only = 0;
03053 iv = i + 1;
03054 }
03055
03056 while(!varname_completed
03057 && iv < l_string
03058 && jv < sizeof(rawvarname) - 1)
03059 {
03060 c = string[iv++];
03061
03062 if((name_only && !(isalnum(c) || c == '_'))
03063 || (!name_only && c == ')'))
03064 {
03065 varname_completed = 1;
03066
03067 if(name_only)
03068 iv--;
03069 }
03070 else
03071 {
03072 rawvarname[jv++] = c;
03073 }
03074 }
03075
03076 if(varname_completed || iv == l_string)
03077 {
03078 char *p;
03079
03080 i = iv;
03081
03082 varcontents = NULL;
03083
03084 bzero((char *) varname, sizeof(varname));
03085 bzero((char *) varaux, sizeof(varaux));
03086 varmodifier = ' ';
03087
03088 if((p = strchr(rawvarname, ':')))
03089 {
03090 strncpy(varname, rawvarname, p - rawvarname);
03091
03092 if(strlen(p) >= 2)
03093 {
03094 varmodifier = *(p + 1);
03095 strcpy(varaux, p + 2);
03096 }
03097 }
03098 else
03099 strcpy(varname, rawvarname);
03100
03101 bzero((char *) varbuffer, sizeof(varbuffer));
03102
03103 varcontents = VarGet(varname);
03104
03105 switch(varmodifier)
03106 {
03107 case '-':
03108 if(!varcontents || !strlen(varcontents))
03109 varcontents = varaux;
03110 break;
03111
03112 case '?':
03113 if(!varcontents || !strlen(varcontents))
03114 {
03115 ErrorMessage("%s(%d): ", file_name, file_line);
03116
03117 if(strlen(varaux))
03118 FatalError("%s\n", varaux);
03119 else
03120 FatalError("Undefined variable \"%s\"\n", varname);
03121 }
03122 break;
03123 }
03124
03125 if(varcontents)
03126 {
03127 int l_varcontents = strlen(varcontents);
03128
03129 iv = 0;
03130
03131 while(iv < l_varcontents && j < sizeof(estring) - 1)
03132 estring[j++] = varcontents[iv++];
03133 }
03134 }
03135 else
03136 {
03137 estring[j++] = '$';
03138 }
03139 }
03140 else
03141 {
03142 estring[j++] = c;
03143 }
03144 }
03145
03146 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "ExpandVars, After: %s\n", estring););
03147
03148 return(estring);
03149 }
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165 void LinkDynamicRules()
03166 {
03167 SetLinks(Activation.TcpList, Dynamic.TcpList);
03168 SetLinks(Activation.UdpList, Dynamic.UdpList);
03169 SetLinks(Activation.IcmpList, Dynamic.IcmpList);
03170 }
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188 void SetLinks(RuleTreeNode * activator, RuleTreeNode * activated_by)
03189 {
03190 RuleTreeNode *act_idx;
03191 RuleTreeNode *dyn_idx;
03192 OptTreeNode *act_otn_idx;
03193
03194 act_idx = activator;
03195 dyn_idx = activated_by;
03196
03197
03198 while(act_idx != NULL)
03199 {
03200 if(act_idx->down != NULL)
03201 {
03202 act_otn_idx = act_idx->down;
03203
03204 while(act_otn_idx != NULL)
03205 {
03206 act_otn_idx->RTN_activation_ptr = GetDynamicRTN(act_otn_idx->activates, dyn_idx);
03207
03208 if(act_otn_idx->RTN_activation_ptr != NULL)
03209 {
03210 act_otn_idx->OTN_activation_ptr = GetDynamicOTN(act_otn_idx->activates, act_otn_idx->RTN_activation_ptr);
03211 }
03212 act_otn_idx = act_otn_idx->next;
03213 }
03214 }
03215 act_idx = act_idx->right;
03216 }
03217 }
03218
03219
03220
03221 RuleTreeNode *GetDynamicRTN(int link_number, RuleTreeNode * dynamic_rule_tree)
03222 {
03223 RuleTreeNode *rtn_idx;
03224 ActivateList *act_list;
03225
03226 rtn_idx = dynamic_rule_tree;
03227
03228 while(rtn_idx != NULL)
03229 {
03230 act_list = rtn_idx->activate_list;
03231
03232 while(act_list != NULL)
03233 {
03234 if(act_list->activated_by == link_number)
03235 {
03236 return rtn_idx;
03237 }
03238 act_list = act_list->next;
03239 }
03240
03241 rtn_idx = rtn_idx->right;
03242 }
03243
03244 return NULL;
03245 }
03246
03247
03248
03249
03250 OptTreeNode *GetDynamicOTN(int link_number, RuleTreeNode * dynamic_rule_tree)
03251 {
03252 OptTreeNode *otn_idx;
03253
03254 otn_idx = dynamic_rule_tree->down;
03255
03256 while(otn_idx != NULL)
03257 {
03258 if(otn_idx->activated_by == link_number)
03259 {
03260 return otn_idx;
03261 }
03262 otn_idx = otn_idx->next;
03263 }
03264
03265 return NULL;
03266 }
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280 void ProcessAlertFileOption(char *filespec)
03281 {
03282 pv.alert_filename = ProcessFileOption(filespec);
03283
03284 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"alertfile set to: %s\n",
03285 pv.alert_filename););
03286 return;
03287 }
03288
03289 char *ProcessFileOption(char *filespec)
03290 {
03291 char *filename;
03292 char buffer[STD_BUF];
03293
03294 if(filespec == NULL)
03295 {
03296 FatalError("no arguement in this file option, remove extra ':' at the end of the alert option\n");
03297 }
03298
03299
03300 if(strstr(filespec, "..") != NULL)
03301 {
03302 FatalError("file definition contains \"..\". Do not do that!\n");
03303 }
03304
03305 if(filespec[0] == '/')
03306 {
03307
03308 filename = strdup(filespec);
03309 }
03310 else
03311 {
03312
03313
03314 if(pv.log_dir)
03315 {
03316 strlcpy(buffer, pv.log_dir, STD_BUF);
03317 }
03318 else
03319 {
03320 strlcpy(buffer, "/var/log/snort", STD_BUF);
03321 }
03322
03323 strlcat(buffer, "/", STD_BUF - strlen(buffer));
03324 strlcat(buffer, filespec, STD_BUF - strlen(buffer));
03325 filename = strdup(buffer);
03326 }
03327
03328 if(!pv.quiet_flag)
03329 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"ProcessFileOption: %s\n", filename););
03330
03331 return filename;
03332 }
03333
03334 void ProcessFlowbitsSize(char **args, int nargs)
03335 {
03336 int i;
03337 char *pcEnd;
03338
03339 if(nargs)
03340 {
03341 i = strtol(args[0], &pcEnd, 10);
03342 if(*pcEnd || i < 0 || i > 256)
03343 {
03344 FatalError("%s(%d) => Invalid argument to 'flowbits_size'. "
03345 "Must be a positive integer and less than 256.\n",
03346 file_name, file_line);
03347 }
03348
03349 giFlowbitSize = (unsigned int)i;
03350 }
03351
03352 return;
03353 }
03354
03355 void ProcessEventQueue(char **args, int nargs)
03356 {
03357 int iCtr;
03358
03359 for(iCtr = 0; iCtr < nargs; iCtr++)
03360 {
03361 if(!strcasecmp("max_queue", args[iCtr]))
03362 {
03363 iCtr++;
03364 if(iCtr < nargs)
03365 {
03366 g_event_queue.max_events = atoi(args[iCtr]);
03367 if(g_event_queue.max_events <= 0)
03368 {
03369 FatalError("%s(%d) => Invalid argument to 'max_queue'. "
03370 "Must be a positive integer.\n", file_name,
03371 file_line);
03372 }
03373 }
03374 else
03375 {
03376 FatalError("%s(%d) => No argument to 'max_queue'. "
03377 "Argument must be a positive integer.\n",
03378 file_name, file_line);
03379 }
03380 }
03381 else if(!strcasecmp("log", args[iCtr]))
03382 {
03383 iCtr++;
03384 if(iCtr < nargs)
03385 {
03386 g_event_queue.log_events = atoi(args[iCtr]);
03387 if(g_event_queue.log_events <= 0)
03388 {
03389 FatalError("%s(%d) => Invalid argument to 'log'. "
03390 "Must be a positive integer.\n", file_name,
03391 file_line);
03392 }
03393 }
03394 else
03395 {
03396 FatalError("%s(%d) => No argument to 'log'. "
03397 "Argument must be a positive integer.\n",
03398 file_name, file_line);
03399 }
03400 }
03401 else if(!strcasecmp("order_events", args[iCtr]))
03402 {
03403 iCtr++;
03404 if(iCtr < nargs)
03405 {
03406 if(!strcasecmp("priority", args[iCtr]))
03407 {
03408 g_event_queue.order = SNORT_EVENTQ_PRIORITY;
03409 }
03410 else if(!strcasecmp("content_length", args[iCtr]))
03411 {
03412 g_event_queue.order = SNORT_EVENTQ_CONTENT_LEN;
03413 }
03414 }
03415 else
03416 {
03417 FatalError("%s(%d) => No argument to 'order_events'. "
03418 "Arguments may be either 'priority' or "
03419 "content_length.\n",
03420 file_name, file_line);
03421 }
03422 }
03423 else
03424 {
03425 FatalError("%s(%d) => Invalid argument to 'event_queue'. "
03426 "To configure event_queue, the options 'max_queue', "
03427 "'log', and 'order_events' must be configured.\n",
03428 file_name, file_line);
03429 }
03430 }
03431
03432 return;
03433 }
03434
03435 void ProcessDetectionOptions( char ** args, int nargs )
03436 {
03437 int i;
03438
03439 for(i=0;i<nargs;i++)
03440 {
03441 if( !strcasecmp(args[i],"search-method") )
03442 {
03443 i++;
03444 if( i < nargs )
03445 {
03446 if(fpSetDetectSearchMethod(args[i]))
03447 {
03448 FatalError("%s (%d)=> Invalid argument to 'search-method'"
03449 ". Must be either 'mwm' or 'ac'.\n",
03450 file_name, file_line);
03451 }
03452 }
03453 else
03454 {
03455 FatalError("%s (%d)=> No argument to 'search-method'. "
03456 "Must be either 'mwm' or 'ac'.\n",
03457 file_name, file_line);
03458 }
03459 }
03460 else if(!strcasecmp(args[i], "debug"))
03461 {
03462 fpSetDebugMode();
03463 }
03464 else if(!strcasecmp(args[i], "no_stream_inserts"))
03465 {
03466 fpSetStreamInsert();
03467 }
03468 else if(!strcasecmp(args[i], "max_queue_events"))
03469 {
03470 i++;
03471 if(i < nargs)
03472 {
03473 if(fpSetMaxQueueEvents(atoi(args[i])))
03474 {
03475 FatalError("%s (%d)=> Invalid argument to "
03476 "'max_queue_events'. Argument must "
03477 "be greater than 0.\n",
03478 file_name, file_line);
03479 }
03480 }
03481 }
03482 else
03483 {
03484 FatalError("%s (%d)=> '%s' is an invalid option to the "
03485 "'config detection:' configuration.\n",
03486 file_name, file_line, args[i]);
03487 }
03488 }
03489 }
03490
03491 void ProcessResetMac(char ** args, int nargs)
03492 {
03493 #ifdef GIDS
03494 #ifndef IPFW
03495
03496 int i = 0;
03497 int num_macargs=nargs;
03498 char **macargs;
03499
03500 macargs = mSplit(args[0], ":", 6, &num_macargs, '\\');
03501
03502 if(num_macargs != 6)
03503 {
03504 FatalError("%s (%d)=> '%s' is not a valid macaddress "
03505 "for layer2resets\n",
03506 file_name, file_line, args[0]);
03507 }
03508
03509 for(i = 0; i < num_macargs; i++)
03510 pv.enet_src[i] = (u_int8_t) strtoul(macargs[i], NULL, 16);
03511
03512 #endif
03513 #endif
03514
03515 return;
03516 }
03517
03518 void ParseConfig(char *rule)
03519 {
03520 char ** toks;
03521 char **rule_toks = NULL;
03522 char **config_decl = NULL;
03523 char *args = NULL;
03524 char *config;
03525 int num_rule_toks = 0, num_config_decl_toks = 0, num_toks=0;
03526
03527 rule_toks = mSplit(rule, ":", 2, &num_rule_toks, 0);
03528 if(num_rule_toks > 1)
03529 {
03530 args = rule_toks[1];
03531 }
03532
03533 config_decl = mSplit(rule_toks[0], " ", 2, &num_config_decl_toks, '\\');
03534 if(num_config_decl_toks != 2)
03535 {
03536 FatalError("unable to parse config: %s\n", rule);
03537 }
03538
03539 config = config_decl[1];
03540
03541 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Config: %s\n", config););
03542 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Args: %s\n", args););
03543
03544 if(!strcasecmp(config, "order"))
03545 {
03546 if(!pv.rules_order_flag)
03547 OrderRuleLists(args);
03548 else
03549 LogMessage("Commandline option overiding rule file config\n");
03550
03551 mSplitFree(&rule_toks,num_rule_toks);
03552 mSplitFree(&config_decl,num_config_decl_toks);
03553
03554 return;
03555 }
03556 else if(!strcasecmp(config, "alertfile"))
03557 {
03558 toks = mSplit(args, " ", 1, &num_toks, 0);
03559
03560 ProcessAlertFileOption(toks[0]);
03561
03562 mSplitFree( &toks, num_toks );
03563 mSplitFree(&rule_toks,num_rule_toks);
03564 mSplitFree(&config_decl,num_config_decl_toks);
03565 return;
03566 }
03567 else if(!strcasecmp(config, "classification"))
03568 {
03569 ParseClassificationConfig(args);
03570
03571 mSplitFree(&rule_toks,num_rule_toks);
03572 mSplitFree(&config_decl,num_config_decl_toks);
03573 return;
03574 }
03575 else if(!strcasecmp(config, "detection"))
03576 {
03577 toks = mSplit(args, ", ",20, &num_toks, 0);
03578 ProcessDetectionOptions(toks,num_toks);
03579 mSplitFree( &toks, num_toks );
03580 mSplitFree(&rule_toks,num_rule_toks);
03581 mSplitFree(&config_decl,num_config_decl_toks);
03582 return;
03583 }
03584 else if(!strcasecmp(config, "flowbits_size"))
03585 {
03586 toks = mSplit(args, ", ",20, &num_toks, 0);
03587 ProcessFlowbitsSize(toks, num_toks);
03588 mSplitFree( &toks, num_toks );
03589 mSplitFree(&rule_toks,num_rule_toks);
03590 mSplitFree(&config_decl,num_config_decl_toks);
03591 return;
03592 }
03593 else if(!strcasecmp(config, "event_queue"))
03594 {
03595 toks = mSplit(args, ", ", 20, &num_toks, 0);
03596 ProcessEventQueue(toks, num_toks);
03597 mSplitFree( &toks, num_toks );
03598 mSplitFree(&rule_toks,num_rule_toks);
03599 mSplitFree(&config_decl,num_config_decl_toks);
03600 return;
03601 }
03602 else if(!strcasecmp(config, "layer2resets"))
03603 {
03604 if(args)
03605 {
03606 toks = mSplit(args, " ", 1, &num_toks, 0);
03607 ProcessResetMac(toks, num_toks);
03608
03609 mSplitFree( &toks, num_toks );
03610 }
03611
03612 #ifdef GIDS
03613 #ifndef IPFW
03614
03615 pv.layer2_resets = 1;
03616
03617 #endif
03618 #endif
03619
03620 mSplitFree(&rule_toks,num_rule_toks);
03621 mSplitFree(&config_decl,num_config_decl_toks);
03622
03623 return;
03624
03625 }
03626 else if(!strcasecmp(config, "ipfw_reinject_rule"))
03627 {
03628 if(args)
03629 {
03630 toks = mSplit(args, " ", 1, &num_toks, 0);
03631 #ifdef GIDS
03632 #ifdef IPFW
03633
03634 pv.ipfw_reinject_rule = atoi(toks[0]) - 1;
03635
03636 #endif
03637 #endif
03638
03639 mSplitFree( &toks, num_toks );
03640 }
03641
03642 mSplitFree(&rule_toks,num_rule_toks);
03643 mSplitFree(&config_decl,num_config_decl_toks);
03644
03645 return;
03646
03647 }
03648 else if(!strcasecmp(config, "asn1"))
03649 {
03650 toks = mSplit(args, ", ", 20, &num_toks, 0);
03651
03652 if(num_toks > 0)
03653 {
03654 if(asn1_init_mem(atoi(toks[0])))
03655 {
03656 FatalError("%s(%d) => Invalid argument to 'asn1' "
03657 "configuration. Must be a positive integer.\n",
03658 file_name, file_line);
03659 }
03660 }
03661 mSplitFree( &toks, num_toks );
03662 mSplitFree(&rule_toks,num_rule_toks);
03663 mSplitFree(&config_decl,num_config_decl_toks);
03664 return;
03665 }
03666 else if(!strcasecmp(config, "dump_chars_only"))
03667 {
03668
03669 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Character payload dump set\n"););
03670 pv.char_data_flag = 1;
03671
03672 mSplitFree(&rule_toks,num_rule_toks);
03673 mSplitFree(&config_decl,num_config_decl_toks);
03674 return;
03675 }
03676 else if(!strcasecmp(config, "dump_payload"))
03677 {
03678
03679 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Payload dump set\n"););
03680 pv.data_flag = 1;
03681
03682 mSplitFree(&rule_toks,num_rule_toks);
03683 mSplitFree(&config_decl,num_config_decl_toks);
03684 return;
03685 }
03686 else if(!strcasecmp(config, "disable_decode_alerts"))
03687 {
03688
03689 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the decoder alerts\n"););
03690 pv.decoder_flags.decode_alerts = 0;
03691
03692 mSplitFree(&rule_toks,num_rule_toks);
03693 mSplitFree(&config_decl,num_config_decl_toks);
03694 return;
03695 }
03696 else if(!strcasecmp(config, "disable_decode_drops"))
03697 {
03698 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the drop of decoder alerts\n"););
03699 pv.decoder_flags.drop_alerts = 0;
03700
03701 mSplitFree(&rule_toks,num_rule_toks);
03702 mSplitFree(&config_decl,num_config_decl_toks);
03703 return;
03704 }
03705 else if(!strcasecmp(config, "disable_tcpopt_experimental_alerts"))
03706 {
03707
03708 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the tcpopt experimental alerts\n"););
03709 pv.decoder_flags.tcpopt_experiment = 0;
03710
03711 mSplitFree(&rule_toks,num_rule_toks);
03712 mSplitFree(&config_decl,num_config_decl_toks);
03713 return;
03714 }
03715 else if(!strcasecmp(config, "disable_tcpopt_experimental_drops"))
03716 {
03717 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the drop of tcpopt exprimental alerts\n"););
03718 pv.decoder_flags.drop_tcpopt_experiment = 0;
03719
03720 mSplitFree(&rule_toks,num_rule_toks);
03721 mSplitFree(&config_decl,num_config_decl_toks);
03722 return;
03723 }
03724
03725 else if(!strcasecmp(config, "disable_tcpopt_obsolete_alerts"))
03726 {
03727
03728 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the tcpopt obsolete alerts\n"););
03729 pv.decoder_flags.tcpopt_obsolete = 0;
03730
03731 mSplitFree(&rule_toks,num_rule_toks);
03732 mSplitFree(&config_decl,num_config_decl_toks);
03733 return;
03734 }
03735 else if(!strcasecmp(config, "disable_tcpopt_obsolete_drops"))
03736 {
03737 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the drop of tcpopt obsolete alerts\n"););
03738 pv.decoder_flags.drop_tcpopt_obsolete = 0;
03739
03740 mSplitFree(&rule_toks,num_rule_toks);
03741 mSplitFree(&config_decl,num_config_decl_toks);
03742 return;
03743 }
03744
03745 else if(!strcasecmp(config, "disable_ttcp_alerts") ||
03746 !strcasecmp(config, "disable_tcpopt_ttcp_alerts"))
03747 {
03748
03749 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the ttcp alerts\n"););
03750 pv.decoder_flags.tcpopt_ttcp = 0;
03751
03752 mSplitFree(&rule_toks,num_rule_toks);
03753 mSplitFree(&config_decl,num_config_decl_toks);
03754 return;
03755 }
03756 else if(!strcasecmp(config, "disable_ttcp_drops"))
03757 {
03758 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the drop of ttcp alerts\n"););
03759 pv.decoder_flags.drop_tcpopt_ttcp = 0;
03760
03761 mSplitFree(&rule_toks,num_rule_toks);
03762 mSplitFree(&config_decl,num_config_decl_toks);
03763 return;
03764 }
03765
03766 else if(!strcasecmp(config, "disable_tcpopt_alerts"))
03767 {
03768
03769 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the all the other tcpopt alerts\n"););
03770 pv.decoder_flags.tcpopt_decode = 0;
03771
03772 mSplitFree(&rule_toks,num_rule_toks);
03773 mSplitFree(&config_decl,num_config_decl_toks);
03774 return;
03775 }
03776 else if(!strcasecmp(config, "disable_tcpopt_drops"))
03777 {
03778 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the drop of all other tcpopt alerts\n"););
03779 pv.decoder_flags.drop_tcpopt_decode = 0;
03780
03781 mSplitFree(&rule_toks,num_rule_toks);
03782 mSplitFree(&config_decl,num_config_decl_toks);
03783 return;
03784 }
03785
03786 else if(!strcasecmp(config, "disable_ipopt_alerts"))
03787 {
03788
03789 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the all the ipopt alerts\n"););
03790 pv.decoder_flags.ipopt_decode = 0;
03791
03792 mSplitFree(&rule_toks,num_rule_toks);
03793 mSplitFree(&config_decl,num_config_decl_toks);
03794 return;
03795 }
03796 else if(!strcasecmp(config, "disable_ipopt_drops"))
03797 {
03798 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "disabling the drop of all the ipopt alerts\n"););
03799 pv.decoder_flags.drop_ipopt_decode = 0;
03800
03801 mSplitFree(&rule_toks,num_rule_toks);
03802 mSplitFree(&config_decl,num_config_decl_toks);
03803 return;
03804 }
03805
03806 else if(!strcasecmp(config, "decode_data_link"))
03807 {
03808
03809 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Decode DLL set\n"););
03810 pv.show2hdr_flag = 1;
03811
03812 mSplitFree(&rule_toks,num_rule_toks);
03813 mSplitFree(&config_decl,num_config_decl_toks);
03814 return;
03815 }
03816 else if(!strcasecmp(config, "bpf_file"))
03817 {
03818
03819 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "BPF file set\n"););
03820
03821 pv.pcap_cmd = read_infile(args);
03822 mSplitFree(&rule_toks,num_rule_toks);
03823 mSplitFree(&config_decl,num_config_decl_toks);
03824 return;
03825 }
03826 else if(!strcasecmp(config, "set_gid"))
03827 {
03828 #ifdef WIN32
03829 FatalError(" Setting the group id is not supported in the WIN32 port of snort!\n");
03830 #else
03831 if((groupname = calloc(strlen(args) + 1, 1)) == NULL)
03832 FatalPrintError("calloc");
03833
03834 bcopy(args, groupname, strlen(args));
03835
03836 if((groupid = atoi(groupname)) == 0)
03837 {
03838 gr = getgrnam(groupname);
03839
03840 if(gr == NULL)
03841 {
03842 ErrorMessage("%s(%d) => Group \"%s\" unknown\n",
03843 file_name, file_line, groupname);
03844 }
03845
03846 groupid = gr->gr_gid;
03847 }
03848 #endif
03849 mSplitFree(&rule_toks,num_rule_toks);
03850 mSplitFree(&config_decl,num_config_decl_toks);
03851
03852 return;
03853 }
03854 else if(!strcasecmp(config, "daemon"))
03855 {
03856 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Daemon mode flag set\n"););
03857 pv.daemon_flag = 1;
03858 flow_set_daemon();
03859 pv.quiet_flag = 1;
03860
03861 mSplitFree(&rule_toks,num_rule_toks);
03862 mSplitFree(&config_decl,num_config_decl_toks);
03863 return;
03864
03865 }
03866 else if(!strcasecmp(config, "reference_net"))
03867 {
03868 GenHomenet(args);
03869 mSplitFree(&rule_toks,num_rule_toks);
03870 mSplitFree(&config_decl,num_config_decl_toks);
03871 return;
03872 }
03873 else if(!strcasecmp(config, "threshold"))
03874 {
03875 ProcessThresholdOptions(args);
03876 mSplitFree(&rule_toks,num_rule_toks);
03877 mSplitFree(&config_decl,num_config_decl_toks);
03878 return;
03879 }
03880 else if(!strcasecmp(config, "interface"))
03881 {
03882 pv.interface = (char *) malloc(strlen(args) + 1);
03883 strlcpy(pv.interface, args, strlen(args)+1);
03884 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Interface = %s\n",
03885 PRINT_INTERFACE(pv.interface)););
03886
03887 if(!pv.readmode_flag)
03888 {
03889 if(pd != NULL)
03890 {
03891 pcap_close(pd);
03892 }
03893
03894 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Opening interface: %s\n",
03895 PRINT_INTERFACE(pv.interface)););
03896
03897 OpenPcap();
03898 }
03899 mSplitFree(&rule_toks,num_rule_toks);
03900 mSplitFree(&config_decl,num_config_decl_toks);
03901 return;
03902 }
03903 else if(!strcasecmp(config, "alert_with_interface_name"))
03904 {
03905 pv.alert_interface_flag = 1;
03906 mSplitFree(&rule_toks,num_rule_toks);
03907 mSplitFree(&config_decl,num_config_decl_toks);
03908 return;
03909 }
03910 else if(!strcasecmp(config, "logdir"))
03911 {
03912 LogMessage("Found logdir config directive (%s)\n", args);
03913 if(!(pv.log_dir = strdup(args)))
03914 FatalError("Out of memory setting log dir from config file\n");
03915 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Log directory = %s\n",
03916 pv.log_dir););
03917 mSplitFree(&rule_toks,num_rule_toks);
03918 mSplitFree(&config_decl,num_config_decl_toks);
03919 return;
03920 }
03921 else if(!strcasecmp(config, "chroot"))
03922 {
03923 LogMessage("Found chroot config directive (%s)\n", args);
03924 if(!(pv.chroot_dir = strdup(args)))
03925 FatalError("Out of memory setting chroot dir from config file\n");
03926 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Chroot directory = %s\n",
03927 pv.chroot_dir););
03928 mSplitFree(&rule_toks,num_rule_toks);
03929 mSplitFree(&config_decl,num_config_decl_toks);
03930 return;
03931 }
03932 else if(!strcasecmp(config, "umask"))
03933 {
03934 char *p;
03935 long val = 0;
03936 int umaskchange = 1;
03937 int defumask = 0;
03938
03939 umaskchange = 0;
03940
03941 val = strtol(args, &p, 8);
03942 if (*p != '\0' || val < 0 || (val & ~FILEACCESSBITS))
03943 {
03944 FatalError("bad umask %s\n", args);
03945 }
03946 else
03947 {
03948 defumask = val;
03949 }
03950
03951
03952 if (umaskchange)
03953 {
03954 umask(077);
03955 }
03956 else
03957 {
03958 umask(defumask);
03959 }
03960 mSplitFree(&rule_toks,num_rule_toks);
03961 mSplitFree(&config_decl,num_config_decl_toks);
03962 return;
03963 }
03964 else if(!strcasecmp(config, "pkt_count"))
03965 {
03966 pv.pkt_cnt = atoi(args);
03967 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Exiting after %d packets\n", pv.pkt_cnt););
03968 mSplitFree(&rule_toks,num_rule_toks);
03969 mSplitFree(&config_decl,num_config_decl_toks);
03970 return;
03971 }
03972 else if(!strcasecmp(config, "nolog"))
03973 {
03974 pv.log_mode = LOG_NONE;
03975 pv.log_cmd_override = 1;
03976 mSplitFree(&rule_toks,num_rule_toks);
03977 mSplitFree(&config_decl,num_config_decl_toks);
03978 return;
03979 }
03980 else if(!strcasecmp(config, "obfuscate"))
03981 {
03982 pv.obfuscation_flag = 1;
03983 mSplitFree(&rule_toks,num_rule_toks);
03984 mSplitFree(&config_decl,num_config_decl_toks);
03985 return;
03986 }
03987 else if(!strcasecmp(config, "no_promisc"))
03988 {
03989 pv.promisc_flag = 0;
03990 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Promiscuous mode disabled!\n"););
03991 mSplitFree(&rule_toks,num_rule_toks);
03992 mSplitFree(&config_decl,num_config_decl_toks);
03993 return;
03994 }
03995 else if(!strcasecmp(config, "snaplen"))
03996 {
03997 pv.pkt_snaplen = atoi(args);
03998 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Snaplength of Packets set to: %d\n",
03999 pv.pkt_snaplen););
04000 mSplitFree(&rule_toks,num_rule_toks);
04001 mSplitFree(&config_decl,num_config_decl_toks);
04002 return;
04003 }
04004 else if(!strcasecmp(config, "quiet"))
04005 {
04006 pv.quiet_flag = 1;
04007 mSplitFree(&rule_toks,num_rule_toks);
04008 mSplitFree(&config_decl,num_config_decl_toks);
04009 return;
04010 }
04011 else if(!strcasecmp(config, "read_bin_file"))
04012 {
04013 strlcpy(pv.readfile, args, STD_BUF);
04014 pv.readmode_flag = 1;
04015 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Opening file: %s\n", pv.readfile););
04016
04017
04018 OpenPcap();
04019 mSplitFree(&rule_toks,num_rule_toks);
04020 mSplitFree(&config_decl,num_config_decl_toks);
04021 return;
04022 }
04023 else if(!strcasecmp(config, "checksum_mode"))
04024 {
04025 int num_atoks,i;
04026 char **atoks;
04027
04028 atoks = mSplit(args, " ",10 , &num_atoks, 0);
04029
04030 for(i=0;i<num_atoks;i++)
04031 {
04032 args=atoks[i];
04033
04034 if(args == NULL || !strcasecmp(args, "all"))
04035 {
04036 pv.checksums_mode = DO_IP_CHECKSUMS | DO_TCP_CHECKSUMS |
04037 DO_UDP_CHECKSUMS | DO_ICMP_CHECKSUMS;
04038 }
04039 else if(!strcasecmp(args, "none"))
04040 {
04041 pv.checksums_mode = 0;
04042 }
04043
04044 else if(!strcasecmp(args, "noip"))
04045 {
04046 pv.checksums_mode ^= DO_IP_CHECKSUMS;
04047 }
04048 else if(!strcasecmp(args, "notcp"))
04049 {
04050 pv.checksums_mode ^= DO_TCP_CHECKSUMS;
04051 }
04052 else if(!strcasecmp(args, "noudp"))
04053 {
04054 pv.checksums_mode ^= DO_UDP_CHECKSUMS;
04055 }
04056 else if(!strcasecmp(args, "noicmp"))
04057 {
04058 pv.checksums_mode ^= DO_ICMP_CHECKSUMS;
04059 }
04060
04061 else if(!strcasecmp(args, "ip"))
04062 {
04063 pv.checksums_mode |= DO_IP_CHECKSUMS;
04064 }
04065 else if(!strcasecmp(args, "tcp"))
04066 {
04067 pv.checksums_mode |= DO_TCP_CHECKSUMS;
04068 }
04069 else if(!strcasecmp(args, "udp"))
04070 {
04071 pv.checksums_mode |= DO_UDP_CHECKSUMS;
04072 }
04073 else if(!strcasecmp(args, "icmp"))
04074 {
04075 pv.checksums_mode |= DO_ICMP_CHECKSUMS;
04076 }
04077
04078 }
04079
04080 mSplitFree(&atoks,num_atoks);
04081 mSplitFree(&rule_toks,num_rule_toks);
04082 mSplitFree(&config_decl,num_config_decl_toks);
04083 return;
04084 }
04085 else if(!strcasecmp(config, "set_uid"))
04086 {
04087 #ifdef WIN32
04088 FatalError("Setting the user id is not supported in the WIN32 port of snort!\n");
04089 #else
04090 if((username = calloc(strlen(args) + 1, 1)) == NULL)
04091 FatalPrintError("malloc");
04092
04093 bcopy(args, username, strlen(args));
04094
04095 if((userid = atoi(username)) == 0)
04096 {
04097 pw = getpwnam(username);
04098 if(pw == NULL)
04099 FatalError("User \"%s\" unknown\n", username);
04100
04101 userid = pw->pw_uid;
04102 }
04103 else
04104 {
04105 pw = getpwuid(userid);
04106 if(pw == NULL)
04107 FatalError(
04108 "Can not obtain username for uid: %lu\n",
04109 (u_long) userid);
04110 }
04111
04112 if(groupname == NULL)
04113 {
04114 char name[256];
04115
04116 snprintf(name, 255, "%lu", (u_long) pw->pw_gid);
04117
04118 if((groupname = calloc(strlen(name) + 1, 1)) == NULL)
04119 {
04120 FatalPrintError("malloc");
04121 }
04122 groupid = pw->pw_gid;
04123 }
04124
04125 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "UserID: %lu GroupID: %lu\n",
04126 (unsigned long) userid, (unsigned long) groupid););
04127 #endif
04128 mSplitFree(&rule_toks,num_rule_toks);
04129 mSplitFree(&config_decl,num_config_decl_toks);
04130 return;
04131 }
04132 else if(!strcasecmp(config, "utc"))
04133 {
04134 pv.use_utc = 1;
04135 mSplitFree(&rule_toks,num_rule_toks);
04136 mSplitFree(&config_decl,num_config_decl_toks);
04137 return;
04138 }
04139 else if(!strcasecmp(config, "verbose"))
04140 {
04141 pv.verbose_flag = 1;
04142 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Verbose Flag active\n"););
04143 mSplitFree(&rule_toks,num_rule_toks);
04144 mSplitFree(&config_decl,num_config_decl_toks);
04145 return;
04146 }
04147 else if(!strcasecmp(config, "dump_payload_verbose"))
04148 {
04149 DEBUG_WRAP(DebugMessage(DEBUG_INIT,
04150 "Verbose packet bytecode dumps enabled\n"););
04151
04152 pv.verbose_bytedump_flag = 1;
04153 mSplitFree(&rule_toks,num_rule_toks);
04154 mSplitFree(&config_decl,num_config_decl_toks);
04155 return;
04156 }
04157 else if(!strcasecmp(config, "show_year"))
04158 {
04159 pv.include_year = 1;
04160 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Enabled year in timestamp\n"););
04161 mSplitFree(&rule_toks,num_rule_toks);
04162 mSplitFree(&config_decl,num_config_decl_toks);
04163 return;
04164 }
04165 else if(!strcasecmp(config, "stateful"))
04166 {
04167 pv.assurance_mode = ASSURE_EST;
04168 mSplitFree(&rule_toks,num_rule_toks);
04169 mSplitFree(&config_decl,num_config_decl_toks);
04170 return;
04171 }
04172 else if(!strcasecmp(config, "min_ttl"))
04173 {
04174 if(args)
04175 {
04176 pv.min_ttl = atoi(args);
04177 }
04178 else
04179 {
04180 FatalError("config min_ttl requires an argument\n");
04181 }
04182 mSplitFree(&rule_toks,num_rule_toks);
04183 mSplitFree(&config_decl,num_config_decl_toks);
04184 return;
04185 }
04186 else if(!strcasecmp(config, "reference"))
04187 {
04188 if(args)
04189 {
04190 ParseReferenceSystemConfig(args);
04191 }
04192 else
04193 {
04194 ErrorMessage("%s(%d) => Reference config without "
04195 "arguments\n", file_name, file_line);
04196 }
04197 mSplitFree(&rule_toks,num_rule_toks);
04198 mSplitFree(&config_decl,num_config_decl_toks);
04199 return;
04200 }
04201 else if (!strcasecmp(config, "ignore_ports"))
04202 {
04203 LogMessage("Found ignore_ports config directive (%s)\n", args);
04204 ParsePortList(args);
04205 mSplitFree(&rule_toks,num_rule_toks);
04206 mSplitFree(&config_decl,num_config_decl_toks);
04207 return;
04208 }
04209
04210 FatalError("Unknown config directive: %s\n", rule);
04211
04212
04213 return;
04214 }
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232 void ParsePortList(char *args)
04233 {
04234 char ** toks;
04235 int num_toks = 0;
04236 int i, p;
04237 u_short hi_port, lo_port;
04238 int protocol;
04239 int not_flag;
04240
04241 toks = mSplit(args, " ", 65535, &num_toks, 0);
04242
04243 if ( !num_toks )
04244 {
04245 FatalError("%s(%d) => config ignore_ports: Empty port list.\n",
04246 file_name, file_line);
04247 }
04248
04249 protocol = WhichProto(toks[0]);
04250
04251 if ( !(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP) )
04252 {
04253 FatalError("%s(%d) => Invalid protocol: %s\n", file_name, file_line, toks[0]);
04254 }
04255
04256 for ( i = 1; i < num_toks; i++ )
04257 {
04258
04259 ParsePort(toks[i], &hi_port, &lo_port, toks[0], ¬_flag);
04260
04261 for ( p = lo_port; p <= hi_port; p++ )
04262 pv.ignore_ports[p] = protocol;
04263 }
04264
04265 mSplitFree(&toks, num_toks);
04266 }
04267
04268
04269
04270 int checkKeyword(char *keyword)
04271 {
04272 RuleListNode *node = RuleLists;
04273
04274 if(RuleType(keyword) != RULE_UNKNOWN)
04275 {
04276 return 1;
04277 }
04278
04279
04280 while(node != NULL)
04281 {
04282 if(!strcasecmp(node->name, keyword))
04283 {
04284 return 1;
04285 }
04286
04287 node = node->next;
04288 }
04289
04290 return 0;
04291 }
04292
04293 void ParseRuleTypeDeclaration(FILE* rule_file, char *rule)
04294 {
04295 char *input;
04296 char *keyword;
04297 char **toks;
04298 int num_toks;
04299 int type;
04300 int rval = 1;
04301 ListHead *listhead = NULL;
04302
04303 toks = mSplit(rule, " ", 10, &num_toks, 0);
04304 keyword = strdup(toks[1]);
04305
04306
04307 if(checkKeyword(keyword))
04308 {
04309 FatalError("%s(%d): Duplicate keyword: %s\n",
04310 file_name, file_line, keyword);
04311 }
04312
04313 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Declaring new rule type: %s\n", keyword););
04314
04315 if(num_toks > 2)
04316 {
04317 if(strcasecmp("{", toks[2]) != 0)
04318 {
04319 FatalError("%s(%d): Syntax error: %s\n",
04320 file_name, file_line, rule);
04321 }
04322 }
04323 else
04324 {
04325 input = ReadLine(rule_file);
04326 free(input);
04327 }
04328
04329 input = ReadLine(rule_file);
04330
04331 mSplitFree(&toks, num_toks);
04332
04333 toks = mSplit(input, " ", 10, &num_toks, 0);
04334
04335
04336 if(!strcasecmp("type", toks[0]))
04337 {
04338 type = RuleType(toks[1]);
04339
04340 if((type != RULE_LOG) && (type != RULE_PASS) && (type != RULE_ALERT) &&
04341 (type != RULE_ACTIVATE) && (type != RULE_DYNAMIC))
04342 {
04343 FatalError("%s(%d): Invalid type for rule type declaration: %s\n", file_name, file_line, toks[1]);
04344 }
04345
04346 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"\ttype(%i): %s\n", type, toks[1]););
04347
04348 if(type == RULE_PASS)
04349 {
04350 rval = 0;
04351 }
04352
04353 listhead = CreateRuleType(keyword, type, rval, NULL);
04354 }
04355 else
04356 {
04357 FatalError("%s(%d): Type not defined for rule file declaration: %s\n", file_name, file_line, keyword);
04358 }
04359
04360 free(input);
04361 input = ReadLine(rule_file);
04362
04363 mSplitFree(&toks, num_toks);
04364
04365
04366 toks = mSplit(input, " ", 2, &num_toks, 0);
04367
04368 while(strcasecmp("}", toks[0]) != 0)
04369 {
04370 if(RuleType(toks[0]) != RULE_OUTPUT)
04371 {
04372 FatalError("%s(%d): Not an output plugin declaration: %s\n", file_name, file_line, keyword);
04373 }
04374
04375 head_tmp = listhead;
04376 ParseOutputPlugin(input);
04377 head_tmp = NULL;
04378 free(input);
04379 input = ReadLine(rule_file);
04380
04381 mSplitFree(&toks, num_toks);
04382 toks = mSplit(input, " ", 2, &num_toks, 0);
04383 }
04384
04385 mSplitFree(&toks, num_toks);
04386
04387 pv.num_rule_types++;
04388
04389 return;
04390 }
04391
04392
04393 char *ReadLine(FILE * file)
04394 {
04395 char buf[MAX_LINE_LENGTH+1];
04396 char *index;
04397
04398 bzero((char *) buf, MAX_LINE_LENGTH+1);
04399
04400
04401
04402
04403
04404 while((fgets(buf, MAX_LINE_LENGTH, file)) != NULL)
04405 {
04406 file_line++;
04407 index = buf;
04408
04409 #ifdef DEBUG2
04410 LogMessage("Got line %s (%d): %s\n", file_name, file_line, buf);
04411 #endif
04412
04413 if((*index != '#') && (*index != 0x0a) && (*index != ';')
04414 && (index != NULL))
04415 {
04416
04417 while(isspace((int) *index))
04418 ++index;
04419
04420
04421 return strdup(index);
04422 }
04423 }
04424
04425 return NULL;
04426 }
04427
04428
04429
04430
04431 char *VarSearch(char *name)
04432 {
04433 struct VarEntry *p;
04434 if(VarHead)
04435 {
04436 p = VarHead;
04437 do
04438 {
04439 if(strcasecmp(p->name, name) == 0)
04440 return p->value;
04441 p = p->next;
04442 } while(p != VarHead);
04443 }
04444
04445 return NULL;
04446 }