Changeset 260
- Timestamp:
- Dec 7, 2009, 10:00:29 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/sh_cat.h
r192 r260 167 167 MSG_LOGMON_REP, 168 168 MSG_LOGMON_SUM, 169 MSG_LOGMON_COR, 169 170 #endif 170 171 -
trunk/include/sh_log_evalrule.h
r183 r260 35 35 int sh_eval_gend (const char * str); 36 36 37 /* Process a single log record 38 */ 37 39 int sh_eval_process_msg(struct sh_logrecord * record); 40 41 /* Match correlated rules 42 */ 43 void sh_keep_match(); 44 38 45 #endif -
trunk/include/sh_string.h
r215 r260 84 84 char ** split_array_list(char *line, unsigned int * nfields, size_t * lengths); 85 85 86 /* Return a split_array_list() of a list contained in 'PREFIX\s*( list ).*' 87 */ 88 char ** split_array_braced (char *line, const char * prefix, 89 unsigned int * nfields, size_t * lengths); 90 86 91 /* Replaces fields in s with 'replacement'. Fields are given 87 92 * in the ordered array ovector, comprising ovecnum pairs -
trunk/src/sh_cat.c
r257 r260 159 159 { MSG_LOGMON_REP, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] %s\" time=\"%s\" host=\"%s\" path=\"%s\"") }, 160 160 { MSG_LOGMON_SUM, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] %s\" host=\"%s\" path=\"%s\"") }, 161 { MSG_LOGMON_COR, SH_ERR_SEVERE, EVENT, N_("msg=\"POLICY [Logfile] Correlated events %s\"") }, 161 162 #endif 162 163 … … 488 489 { MSG_LOGMON_REP, SH_ERR_SEVERE, EVENT, N_("msg=<POLICY [Logfile] %s> time=<%s> host=<%s> path=<%s>") }, 489 490 { MSG_LOGMON_SUM, SH_ERR_SEVERE, EVENT, N_("msg=<POLICY [Logfile] %s> host=<%s> path=<%s>") }, 491 { MSG_LOGMON_COR, SH_ERR_SEVERE, EVENT, N_("msg=<POLICY [Logfile] Correlated events %s>") }, 490 492 #endif 491 493 -
trunk/src/sh_log_check.c
r257 r260 28 28 29 29 /* List of supported logfile types, format is 30 * { "TYPE_CODE", Reader_Callback_Function, Parser_Callback_function } 30 * { 31 * "TYPE_CODE", 32 * Reader_Callback_Function, 33 * Parser_Callback_function, 34 * Evaluate_Callback_Function 35 * } 31 36 * If Reader_Callback_Function is NULL, the default (line-oriented 32 37 * text file) reader is used. … … 78 83 plen = strlen(save_dir); 79 84 80 if (SL_TRUE == sl_ok_adds(plen, 1 29))81 { 82 plen += 1 29; /* 64 + 64 + 1*/85 if (SL_TRUE == sl_ok_adds(plen, 130)) 86 { 87 plen += 130; /* 64 + 64 + 2 */ 83 88 path = SH_ALLOC(plen); 84 89 (void) sl_snprintf(path, plen, "%s/%lu_%lu", save_dir, … … 860 865 { 861 866 sh_check_watches(); 867 sh_keep_match(); 862 868 } 863 869 SH_MUTEX_UNLOCK(mutex_logmon_check); … … 1036 1042 1037 1043 /* Define a check rule. 1038 * Format: Queue_Label : Regex 1039 * TYPE must be 'report' or 'sum' 1044 * Format: [KEEP(seconds,label):]Queue_Label : Regex 1045 * KEEP indicates that we keep the label, to perform 1046 * correlation matching 1040 1047 */ 1041 1048 static int sh_logmon_add_rule (const char * str) -
trunk/src/sh_log_evalrule.c
r203 r260 89 89 }; 90 90 91 enum { 92 RFL_ISRULE = 1 << 0, 93 RFL_ISGROUP = 1 << 1, 94 RFL_KEEP = 1 << 2 95 }; 96 97 /*--------------------------------------------------------------*/ 98 99 struct sh_keep 100 { 101 sh_string * label; /* label of keep rule */ 102 unsigned long delay; /* valid delay */ 103 time_t last; /* seen at */ 104 struct sh_keep * next; 105 }; 106 107 static struct sh_keep * keeplist = NULL; 108 static struct sh_keep * keeplast = NULL; 109 static unsigned long keepcount = 0; 110 111 static void sh_keep_free(void * item) 112 { 113 struct sh_keep * keep = (struct sh_keep *) item; 114 if (!keep) 115 return; 116 sh_string_destroy(&(keep->label)); 117 SH_FREE(keep); 118 } 119 120 static void sh_keep_destroy() 121 { 122 struct sh_keep * keep; 123 124 while (keeplist) 125 { 126 keep = keeplist; 127 keeplist = keep->next; 128 sh_keep_free(keep); 129 --keepcount; 130 } 131 keeplist = NULL; 132 keeplast = NULL; 133 keepcount = 0; 134 } 135 136 static int sh_keep_add(sh_string * label, unsigned long delay, time_t last) 137 { 138 struct sh_keep * keep = SH_ALLOC(sizeof(struct sh_keep)); 139 140 keep->label = sh_string_copy(label); 141 keep->delay = delay; 142 keep->last = last; 143 keep->next = NULL; 144 145 if (keeplast && keeplist) 146 { 147 keeplast->next = keep; 148 keeplast = keep; 149 } 150 else 151 { 152 keeplist = keep; 153 keeplast = keeplist; 154 } 155 ++keepcount; 156 return 0; 157 } 158 159 int sh_keep_comp(const void * a, const void * b) 160 { 161 return ( (int)(((struct sh_keep *)a)->last) - 162 (int)(((struct sh_keep *)b)->last) ); 163 } 164 165 static sh_string * sh_keep_eval() 166 { 167 unsigned long count = 0; 168 sh_string * res = NULL; 169 time_t now = time(NULL); 170 struct sh_keep * keep = keeplist; 171 struct sh_keep * prev = keeplist; 172 struct sh_keep * arr; 173 174 if (keepcount > 0) 175 { 176 arr = SH_ALLOC (keepcount * sizeof(struct sh_keep)); 177 178 while (count < keepcount && keep) 179 { 180 if ((now > keep->last) && ((unsigned long)(now - keep->last) <= keep->delay)) 181 { 182 memcpy(&(arr[count]), keep, sizeof(struct sh_keep)); 183 ++count; 184 prev = keep; 185 keep = keep->next; 186 } 187 else /* Too old or in future, delete it */ 188 { 189 if (keep != keeplist) 190 { 191 prev->next = keep->next; 192 sh_keep_free(keep); 193 keep = prev->next; 194 --keepcount; 195 } 196 else /* list head */ 197 { 198 keeplist = keep->next; 199 prev = keeplist; 200 sh_keep_free(keep); 201 keep = keeplist; 202 --keepcount; 203 } 204 } 205 } 206 207 if (count > 0) 208 { 209 unsigned long i; 210 qsort(arr, count, sizeof(struct sh_keep), sh_keep_comp); 211 res = sh_string_copy(arr[0].label); 212 for (i = 1; i < count; ++i) 213 res = sh_string_add(res, arr[i].label); 214 } 215 SH_FREE(arr); 216 } 217 return res; 218 } 219 220 struct sh_mkeep 221 { 222 sh_string * label; /* label of match rule */ 223 pcre * rule; /* compiled regex for rule */ 224 struct sh_qeval * queue; /* assigned queue */ 225 struct sh_mkeep * next; 226 }; 227 228 struct sh_mkeep * mkeep_list = NULL; 229 230 static struct sh_qeval * find_queue(const char * str); 231 232 static int sh_keep_match_add(const char * str, const char * queue, const char * pattern) 233 { 234 unsigned int nfields = 1; /* seconds:label */ 235 size_t lengths[1]; 236 char * new = sh_util_strdup(str); 237 char ** splits = split_array_braced(new, _("CORRELATE"), &nfields, lengths); 238 239 if (nfields == 1 && lengths[0] > 0) 240 { 241 struct sh_mkeep * mkeep = SH_ALLOC(sizeof(struct sh_mkeep)); 242 const char * error; 243 int erroffset; 244 struct sh_qeval * rqueue = NULL; 245 246 mkeep->rule = pcre_compile(pattern, PCRE_NO_AUTO_CAPTURE, 247 &error, &erroffset, NULL); 248 if (!(mkeep->rule)) 249 { 250 sh_string * msg = sh_string_new(0); 251 sh_string_add_from_char(msg, _("Bad regex: ")); 252 sh_string_add_from_char(msg, pattern); 253 254 SH_MUTEX_LOCK(mutex_thread_nolog); 255 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 256 sh_string_str(msg), 257 _("sh_keep_match_add")); 258 SH_MUTEX_UNLOCK(mutex_thread_nolog); 259 sh_string_destroy(&msg); 260 261 SH_FREE(splits); 262 SH_FREE(mkeep); 263 SH_FREE(new); 264 return -1; 265 } 266 267 if (0 != strcmp(queue, _("trash"))) 268 { 269 270 rqueue = find_queue(queue); 271 if (!rqueue) 272 { 273 pcre_free(mkeep->rule); 274 SH_FREE(splits); 275 SH_FREE(mkeep); 276 SH_FREE(new); 277 return -1; 278 } 279 } 280 281 mkeep->queue = rqueue; 282 mkeep->label = sh_string_new_from_lchar(splits[0], strlen(splits[0])); 283 mkeep->next = mkeep_list; 284 mkeep_list = mkeep; 285 } 286 SH_FREE(new); 287 return 0; 288 } 289 290 static void sh_keep_match_del() 291 { 292 struct sh_mkeep * mkeep = mkeep_list; 293 while (mkeep) 294 { 295 mkeep_list = mkeep->next; 296 sh_string_destroy(&(mkeep->label)); 297 pcre_free(mkeep->rule); 298 mkeep = mkeep_list; 299 } 300 mkeep_list = NULL; 301 } 302 303 static struct sh_mkeep ** dummy_mkeep; 304 305 void sh_keep_match() 306 { 307 if (mkeep_list) 308 { 309 sh_string * res = sh_keep_eval(); 310 311 if (res) 312 { 313 struct sh_mkeep * mkeep = mkeep_list; 314 315 dummy_mkeep = &mkeep; 316 317 while (mkeep) 318 { 319 int val = pcre_exec(mkeep->rule, NULL, 320 sh_string_str(res), (int)sh_string_len(res), 321 0, 0, NULL, 0); 322 if (val >= 0) 323 { 324 char * tmp; 325 SH_MUTEX_LOCK(mutex_thread_nolog); 326 tmp = sh_util_safe_name (sh_string_str(mkeep->label)); 327 sh_error_handle (mkeep->queue->severity, FIL__, __LINE__, 0, 328 MSG_LOGMON_COR, tmp); 329 SH_FREE(tmp); 330 SH_MUTEX_UNLOCK(mutex_thread_nolog); 331 } 332 mkeep = mkeep->next; 333 } 334 sh_string_destroy(&res); 335 } 336 } 337 return; 338 } 339 340 /*--------------------------------------------------------------*/ 341 91 342 struct sh_geval /* Group of rules (may be a single rule) */ 92 343 { … … 97 348 int ovecnum; /* how many captured */ 98 349 int captures; /* (captures+1)*3 required */ 350 int flags; /* bit flags */ 351 unsigned long delay; /* delay for keep rules */ 99 352 zAVLTree * counterlist; /* counters if EVAL_SUM */ 100 353 struct sh_qeval * queue; /* queue for this rule */ … … 178 431 ng = SH_ALLOC(sizeof(struct sh_geval)); 179 432 ng->label = sh_string_new_from_lchar(splits[0], lengths[0]); 433 ng->flags = RFL_ISGROUP; 434 180 435 ng->rule = group; 181 436 ng->rule_extra = group_extra; … … 384 639 } 385 640 641 char * get_keep(char * str, unsigned long * seconds) 642 { 643 char * res = NULL; 644 char * endptr = NULL; 645 646 unsigned int nfields = 2; /* seconds:label */ 647 size_t lengths[2]; 648 char * new = sh_util_strdup(str); 649 char ** splits = split_array_braced(new, _("KEEP"), &nfields, lengths); 650 651 if (nfields == 2 && lengths[0] > 0 && lengths[1] > 0) 652 { 653 *seconds = strtoul(splits[0], &endptr, 10); 654 if ((endptr == '\0' || endptr != splits[0]) && (*seconds != ULONG_MAX)) 655 { 656 res = sh_util_strdup(splits[1]); 657 } 658 } 659 if (splits) 660 SH_FREE(splits); 661 SH_FREE(new); 662 return res; 663 } 664 386 665 static struct sh_qeval ** dummy_queue; 666 static char ** dummy_dstr; 387 667 388 668 int sh_eval_radd (const char * str) … … 398 678 unsigned int nfields = 2; /* queue:regex */ 399 679 size_t lengths[2]; 400 char * new = sh_util_strdup(str);680 char * new = sh_util_strdup(str); 401 681 char ** splits = split_array(new, &nfields, ':', lengths); 402 682 683 int qpos = 0; 684 int rpos = 1; 685 unsigned long dsec = 0; 686 char * dstr = NULL; 687 403 688 dummy_queue = &queue; 404 405 if (nfields != 2) 689 dummy_dstr = &dstr; 690 691 if (nfields < 2 || nfields > 3) 406 692 { 407 693 SH_FREE(splits); … … 410 696 } 411 697 412 if (0 != strcmp(splits[0], _("trash"))) 413 { 414 queue = find_queue(splits[0]); 415 if (!queue) 416 { 417 SH_FREE(splits); 418 SH_FREE(new); 419 return -1; 420 } 421 } 422 423 rule = pcre_compile(splits[1], 0, 698 if (nfields == 3) 699 { 700 /* KEEP(nsec):queue:regex 701 */ 702 dstr = get_keep(splits[0], &dsec); 703 if (!dstr) 704 { 705 /* CORRELATE:queue:regex 706 */ 707 int retval = sh_keep_match_add(splits[0], splits[1], splits[2]); 708 SH_FREE(splits); 709 SH_FREE(new); 710 return retval; 711 } 712 ++qpos; ++rpos; 713 } 714 715 if (0 != strcmp(splits[qpos], _("trash"))) 716 { 717 queue = find_queue(splits[qpos]); 718 if (!queue) 719 { 720 SH_FREE(splits); 721 SH_FREE(new); 722 return -1; 723 } 724 } 725 726 rule = pcre_compile(splits[rpos], 0, 424 727 &error, &erroffset, NULL); 425 728 if (!rule) … … 427 730 sh_string * msg = sh_string_new(0); 428 731 sh_string_add_from_char(msg, _("Bad regex: ")); 429 sh_string_add_from_char(msg, splits[ 1]);732 sh_string_add_from_char(msg, splits[rpos]); 430 733 431 734 SH_MUTEX_LOCK(mutex_thread_nolog); … … 446 749 { 447 750 char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); 448 sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Adding rule: |%s| with %d captures"), 449 splits[1], captures); 751 if (dstr) 752 sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Adding rule: |%s| with %d captures, keep(%lu,%s)"), 753 splits[rpos], captures, dsec, dstr); 754 else 755 sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Adding rule: |%s| with %d captures"), 756 splits[rpos], captures); 450 757 SH_MUTEX_LOCK(mutex_thread_nolog); 451 758 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, … … 455 762 } 456 763 457 DEBUG("adding rule: |%s| with %d captures\n", splits[ 1], captures);764 DEBUG("adding rule: |%s| with %d captures\n", splits[rpos], captures); 458 765 459 766 SH_FREE(splits); … … 462 769 nr = SH_ALLOC(sizeof(struct sh_geval)); 463 770 nr->label = NULL; 771 nr->flags = RFL_ISRULE; 772 nr->delay = 0; 773 464 774 nr->rule = rule; 465 775 nr->rule_extra = rule_extra; … … 473 783 nr->gnext = NULL; 474 784 785 786 if (dstr) 787 { 788 nr->label = sh_string_new_from_lchar(dstr, strlen(dstr)); 789 nr->flags |= RFL_KEEP; 790 nr->delay = dsec; 791 SH_FREE(dstr); 792 } 793 475 794 /* 476 795 * If there is an open group, add it to its … … 513 832 if (0 != sh_eval_hadd("^.*")) 514 833 { 834 if (nr->label) 835 sh_string_destroy(&(nr->label)); 515 836 SH_FREE(nr->ovector); 516 837 SH_FREE(nr); … … 559 880 else 560 881 { 882 if (nr->label) 883 sh_string_destroy(&(nr->label)); 561 884 SH_FREE(nr->ovector); 562 885 SH_FREE(nr); … … 623 946 } 624 947 948 sh_keep_destroy(); 949 sh_keep_match_del(); 950 951 return; 625 952 } 626 953 … … 636 963 static struct sh_geval ** dummy1; 637 964 638 static struct sh_geval * test_rule (struct sh_geval * rule, sh_string *msg )965 static struct sh_geval * test_rule (struct sh_geval * rule, sh_string *msg, time_t tstamp) 639 966 { 640 967 int res; 641 volatile int count; 968 volatile int count; 969 volatile time_t timestamp = tstamp; 642 970 643 971 dummy1 = &rule; … … 674 1002 { 675 1003 char * emsg = SH_ALLOC(SH_ERRBUF_SIZE); 676 sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Rule %d matches, result = %d"), 677 count, res); 1004 if ( rule->flags & RFL_KEEP ) 1005 sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Rule %d matches, result = %d (keep)"), 1006 count, res); 1007 else 1008 sl_snprintf(emsg, SH_ERRBUF_SIZE, _("Rule %d matches, result = %d"), 1009 count, res); 678 1010 SH_MUTEX_LOCK(mutex_thread_nolog); 679 1011 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, … … 682 1014 SH_FREE(emsg); 683 1015 } 684 DEBUG("debug: rule %d matches, result = %d\n", count, res); 1016 1017 if ( rule->flags & RFL_KEEP ) 1018 { 1019 DEBUG("debug: rule %d matches (keep)\n", count); 1020 sh_keep_add(rule->label, rule->delay, 1021 timestamp == 0 ? time(NULL) : timestamp); 1022 } 1023 685 1024 break; /* return the matching rule; ovector is filled in */ 686 1025 } … … 698 1037 } 699 1038 DEBUG("debug: rule %d did not match\n", count); 1039 700 1040 rule = rule->nextrule; ++count; 701 1041 } while (rule); … … 714 1054 715 1055 static struct sh_geval * test_grules (struct sh_heval * host, 716 sh_string *msg) 1056 sh_string * msg, 1057 time_t timestamp) 717 1058 { 718 1059 struct sh_geval * result = NULL; … … 726 1067 DEBUG("debug: if group\n"); 727 1068 do { 728 if( group->label != NULL)1069 if( (group->label != NULL) && (0 != (group->flags & RFL_ISGROUP))) 729 1070 { 730 /* this is a rule group ; only groups have labels*/1071 /* this is a rule group */ 731 1072 732 1073 if (flag_err_debug == SL_TRUE) … … 747 1088 0, 0, NULL, 0) >= 0) 748 1089 { 749 result = test_rule(group->nextrule, msg );1090 result = test_rule(group->nextrule, msg, timestamp); 750 1091 if (result) 751 1092 break; … … 770 1111 771 1112 DEBUG("debug: else (single rule)\n"); 772 result = test_rule(group, msg );1113 result = test_rule(group, msg, timestamp); 773 1114 if (result) 774 1115 break; … … 783 1124 */ 784 1125 static struct sh_geval * find_rule (sh_string *host, 785 sh_string *msg) 1126 sh_string *msg, 1127 time_t timestamp) 786 1128 { 787 1129 struct sh_geval * result = NULL; … … 796 1138 { 797 1139 /* matching host, check rules/groups of rules */ 798 result = test_grules(hlist, msg );1140 result = test_grules(hlist, msg, timestamp); 799 1141 if (result) 800 1142 break; … … 994 1336 { 995 1337 struct sh_geval * rule = find_rule (record->host, 996 record->message); 1338 record->message, 1339 record->timestamp); 997 1340 998 1341 if (rule) -
trunk/src/sh_string.c
r237 r260 238 238 { 239 239 return split_array_ws_int (line, nfields, lengths, SH_SPLIT_LIST); 240 } 241 242 /* return a split() of a list contained in 'PREFIX\s*( list ).*' 243 */ 244 char ** split_array_braced (char *line, const char * prefix, 245 unsigned int * nfields, size_t * lengths) 246 { 247 char * s = line; 248 char * p; 249 250 while ( *s && isspace((int)*s) ) ++s; 251 if (prefix && 0 != strncmp(s, prefix, strlen(prefix))) 252 return NULL; 253 s = &s[strlen(prefix)]; 254 while ( *s && isspace((int)*s) ) ++s; 255 if (!s || (*s != '(')) 256 return NULL; 257 ++s; 258 p = strchr(s, ')'); 259 if (!p || (*p == *s)) 260 return NULL; 261 *p = '\0'; 262 return split_array_list (s, nfields, lengths); 240 263 } 241 264
Note:
See TracChangeset
for help on using the changeset viewer.