3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 2) as published by the FSF - Free Software
11 * License details at the LICENSE file included with OSSEC or
12 * online at: http://www.ossec.net/en/licensing.html
17 #include "os_regex/os_regex.h"
18 #include "os_xml/os_xml.h"
21 #include "analysisd.h"
22 #include "eventinfo.h"
24 #include "plugin_decoders.h"
29 #define XML_LDECODER "etc/local_decoder.xml"
33 /* Internal functions */
34 char *_loadmemory(char *at, char *str);
35 OSStore *os_decoder_store = NULL;
39 int getDecoderfromlist(char *name)
43 return(OSStore_GetPosition(os_decoder_store, name));
51 int addDecoder2list(char *name)
53 if(os_decoder_store == NULL)
55 os_decoder_store = OSStore_Create();
56 if(os_decoder_store == NULL)
58 merror(LIST_ERROR, ARGV0);
64 if(!OSStore_Put(os_decoder_store, name, NULL))
66 merror(LIST_ADD_ERROR, ARGV0);
75 int os_setdecoderids(char *p_name)
78 OSDecoderNode *child_node;
82 node = OS_GetFirstOSDecoder(p_name);
85 /* Return if no node...
86 * This shouldn't happen here anyways.
96 nnode = node->osdecoder;
97 nnode->id = getDecoderfromlist(nnode->name);
99 /* Id can noit be 0 */
105 child_node = node->child;
113 /* Setting parent id */
115 p_name = nnode->name;
118 /* Also setting on the child nodes */
121 nnode = child_node->osdecoder;
123 if(nnode->use_own_name)
125 nnode->id = getDecoderfromlist(nnode->name);
131 /* Setting parent name */
132 nnode->name = p_name;
136 /* Id can noit be 0 */
141 child_node = child_node->next;
143 }while((node=node->next) != NULL);
149 /* Read attributes */
150 int ReadDecodeAttrs(char **names, char **values)
152 if(!names || !values)
155 if(!names[0] || !values[0])
160 if(strcmp(names[0], "offset") == 0)
164 /* Offsets can be: after_parent, after_prematch
167 if(strcmp(values[0],"after_parent") == 0)
169 offset |= AFTER_PARENT;
171 else if(strcmp(values[0],"after_prematch") == 0)
173 offset |= AFTER_PREMATCH;
175 else if(strcmp(values[0],"after_regex") == 0)
177 offset |= AFTER_PREVREGEX;
181 merror(INV_OFFSET, ARGV0, values[0]);
182 offset |= AFTER_ERROR;
188 /* Invalid attribute */
189 merror(INV_ATTR, ARGV0, names[0]);
195 int ReadDecodeXML(char *file)
198 debug1("ReadDecoderXML File = %s", file);
200 XML_NODE node = NULL;
203 /* These are the available options for the rule configuration */
205 char *xml_plugindecoder = "plugin_decoder";
206 char *xml_decoder = "decoder";
207 char *xml_decoder_name = "name";
208 char *xml_decoder_status = "status";
209 char *xml_usename = "use_own_name";
210 char *xml_parent = "parent";
211 char *xml_program_name = "program_name";
212 char *xml_prematch = "prematch";
213 char *xml_regex = "regex";
214 char *xml_order = "order";
215 char *xml_type = "type";
216 char *xml_fts = "fts";
217 char *xml_ftscomment = "ftscomment";
220 OSDecoderInfo *NULL_Decoder_tmp = NULL;
223 /* Reading the XML */
224 if((i = OS_ReadXML(file,&xml)) < 0)
226 if((i == -2) && (strcmp(file, XML_LDECODER) == 0))
231 merror(XML_ERROR, ARGV0, file, xml.err, xml.err_line);
236 /* Applying any variable found */
237 if(OS_ApplyVariables(&xml) != 0)
239 merror(XML_ERROR_VAR, ARGV0, file, xml.err);
244 /* Getting the root elements */
245 node = OS_GetElementsbyNode(&xml, NULL);
248 if(strcmp(file, XML_LDECODER) != 0)
250 merror(XML_ELEMNULL, ARGV0);
258 /* Zeroing NULL_decoder */
259 os_calloc(1, sizeof(OSDecoderInfo), NULL_Decoder_tmp);
260 NULL_Decoder_tmp->id = 0;
261 NULL_Decoder_tmp->type = SYSLOG;
262 NULL_Decoder_tmp->name = NULL;
263 NULL_Decoder_tmp->fts = 0;
264 NULL_Decoder = (void *)NULL_Decoder_tmp;
271 XML_NODE elements = NULL;
280 if(!node[i]->element ||
281 strcasecmp(node[i]->element, xml_decoder) != 0)
283 merror(XML_INVELEM, ARGV0, node[i]->element);
289 if((!node[i]->attributes) || (!node[i]->values)||
290 (!node[i]->values[0]) || (!node[i]->attributes[0])||
291 (strcasecmp(node[i]->attributes[0],xml_decoder_name)!= 0))
293 merror(XML_INVELEM, ARGV0, node[i]->element);
298 /* Checking for additional entries */
299 if(node[i]->attributes[1] && node[i]->values[1])
301 if(strcasecmp(node[i]->attributes[0],xml_decoder_status)!= 0)
303 merror(XML_INVELEM, ARGV0, node[i]->element);
307 if(node[i]->attributes[2])
309 merror(XML_INVELEM, ARGV0, node[i]->element);
315 /* Getting decoder options */
316 elements = OS_GetElementsbyNode(&xml,node[i]);
319 merror(XML_ELEMNULL, ARGV0);
323 /* Creating the OSDecoderInfo */
324 pi = (OSDecoderInfo *)calloc(1,sizeof(OSDecoderInfo));
327 merror(MEM_ERROR,ARGV0);
332 /* Default values to the list */
335 pi->name = strdup(node[i]->values[0]);
337 pi->plugindecoder = NULL;
341 pi->program_name = NULL;
343 pi->use_own_name = 0;
345 pi->regex_offset = 0;
346 pi->prematch_offset = 0;
353 /* Checking if strdup worked */
356 merror(MEM_ERROR, ARGV0);
361 if(!addDecoder2list(pi->name))
363 merror(MEM_ERROR, ARGV0);
367 /* Looping on all the elements */
370 if(!elements[j]->element)
372 merror(XML_ELEMNULL, ARGV0);
375 else if(!elements[j]->content)
377 merror(XML_VALUENULL, ARGV0, elements[j]->element);
381 /* Checking if it is a child of a rule */
382 else if(strcasecmp(elements[j]->element, xml_parent) == 0)
384 pi->parent = _loadmemory(pi->parent, elements[j]->content);
387 /* Getting the regex */
388 else if(strcasecmp(elements[j]->element,xml_regex) == 0)
391 r_offset = ReadDecodeAttrs(elements[j]->attributes,
392 elements[j]->values);
394 if(r_offset & AFTER_ERROR)
396 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
400 /* Only the first regex entry may have an offset */
401 if(regex && r_offset)
403 merror(DUP_REGEX, ARGV0, pi->name);
404 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
411 pi->regex_offset = r_offset;
417 elements[j]->content);
420 /* Getting the pre match */
421 else if(strcasecmp(elements[j]->element,xml_prematch)==0)
425 r_offset = ReadDecodeAttrs(
426 elements[j]->attributes,
427 elements[j]->values);
429 if(r_offset & AFTER_ERROR)
431 ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
435 /* Only the first prematch entry may have an offset */
436 if(prematch && r_offset)
438 merror(DUP_REGEX, ARGV0, pi->name);
439 ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
444 pi->prematch_offset = r_offset;
448 _loadmemory(prematch,
449 elements[j]->content);
452 /* Getting program name */
453 else if(strcasecmp(elements[j]->element,xml_program_name) == 0)
455 p_name = _loadmemory(p_name, elements[j]->content);
458 /* Getting the fts comment */
459 else if(strcasecmp(elements[j]->element,xml_ftscomment)==0)
463 else if(strcasecmp(elements[j]->element,xml_usename)==0)
465 if(strcmp(elements[j]->content,"true") == 0)
466 pi->use_own_name = 1;
469 else if(strcasecmp(elements[j]->element, xml_plugindecoder) == 0)
472 for(ed_c = 0; plugin_decoders[ed_c] != NULL; ed_c++)
474 if(strcmp(plugin_decoders[ed_c],
475 elements[j]->content) == 0)
477 /* Initializing plugin */
478 void (*dec_init)() = plugin_decoders_init[ed_c];
481 pi->plugindecoder = plugin_decoders_exec[ed_c];
486 /* Decoder not found */
487 if(pi->plugindecoder == NULL)
489 merror(INV_DECOPTION, ARGV0, elements[j]->element,
490 elements[j]->content);
496 /* Getting the type */
497 else if(strcmp(elements[j]->element, xml_type) == 0)
499 if(strcmp(elements[j]->content, "firewall") == 0)
501 else if(strcmp(elements[j]->content, "ids") == 0)
503 else if(strcmp(elements[j]->content, "web-log") == 0)
505 else if(strcmp(elements[j]->content, "syslog") == 0)
507 else if(strcmp(elements[j]->content, "squid") == 0)
509 else if(strcmp(elements[j]->content, "windows") == 0)
511 else if(strcmp(elements[j]->content, "host-information") == 0)
512 pi->type = HOST_INFO;
513 else if(strcmp(elements[j]->content, "ossec") == 0)
517 merror("%s: Invalid decoder type '%s'.",
518 ARGV0, elements[j]->content);
523 /* Getting the order */
524 else if(strcasecmp(elements[j]->element,xml_order)==0)
526 char **norder, **s_norder;
529 /* Maximum number is 8 for the order */
530 norder = OS_StrBreak(',',elements[j]->content, 8);
532 os_calloc(8, sizeof(void *), pi->order);
535 /* Initializing the function pointers */
538 pi->order[order_int] = NULL;
544 /* Checking the values from the order */
547 if(strstr(*norder, "dstuser") != NULL)
549 pi->order[order_int] = (void *)DstUser_FP;
551 else if(strstr(*norder, "srcuser") != NULL)
553 pi->order[order_int] = (void *)SrcUser_FP;
555 /* User is an alias to dstuser */
556 else if(strstr(*norder, "user") != NULL)
558 pi->order[order_int] = (void *)DstUser_FP;
560 else if(strstr(*norder, "srcip") != NULL)
562 pi->order[order_int] = (void *)SrcIP_FP;
564 else if(strstr(*norder, "dstip") != NULL)
566 pi->order[order_int] = (void *)DstIP_FP;
568 else if(strstr(*norder, "srcport") != NULL)
570 pi->order[order_int] = (void *)SrcPort_FP;
572 else if(strstr(*norder, "dstport") != NULL)
574 pi->order[order_int] = (void *)DstPort_FP;
576 else if(strstr(*norder, "protocol") != NULL)
578 pi->order[order_int] = (void *)Protocol_FP;
580 else if(strstr(*norder, "action") != NULL)
582 pi->order[order_int] = (void *)Action_FP;
584 else if(strstr(*norder, "id") != NULL)
586 pi->order[order_int] = (void *)ID_FP;
588 else if(strstr(*norder, "url") != NULL)
590 pi->order[order_int] = (void *)Url_FP;
592 else if(strstr(*norder, "data") != NULL)
594 pi->order[order_int] = (void *)Data_FP;
596 else if(strstr(*norder, "extra_data") != NULL)
598 pi->order[order_int] = (void *)Data_FP;
600 else if(strstr(*norder, "status") != NULL)
602 pi->order[order_int] = (void *)Status_FP;
604 else if(strstr(*norder, "system_name") != NULL)
606 pi->order[order_int] = (void *)SystemName_FP;
610 ErrorExit("decode-xml: Wrong field '%s' in the order"
611 " of decoder '%s'",*norder,pi->name);
623 /* Getting the fts order */
624 else if(strcasecmp(elements[j]->element,xml_fts)==0)
629 /* Maximum number is 8 for the fts */
630 norder = OS_StrBreak(',',elements[j]->content, 8);
632 ErrorExit(MEM_ERROR,ARGV0);
635 /* Saving the initial point to free later */
639 /* Checking the values from the fts */
642 if(strstr(*norder, "dstuser") != NULL)
644 pi->fts|=FTS_DSTUSER;
646 if(strstr(*norder, "user") != NULL)
648 pi->fts|=FTS_DSTUSER;
650 else if(strstr(*norder, "srcuser") != NULL)
652 pi->fts|=FTS_SRCUSER;
654 else if(strstr(*norder, "srcip") != NULL)
658 else if(strstr(*norder, "dstip") != NULL)
662 else if(strstr(*norder, "id") != NULL)
666 else if(strstr(*norder, "location") != NULL)
668 pi->fts|=FTS_LOCATION;
670 else if(strstr(*norder, "data") != NULL)
674 else if(strstr(*norder, "extra_data") != NULL)
678 else if(strstr(*norder, "system_name") != NULL)
680 pi->fts|=FTS_SYSTEMNAME;
682 else if(strstr(*norder, "name") != NULL)
688 ErrorExit("decode-xml: Wrong field '%s' in the fts"
689 " decoder '%s'",*norder, pi->name);
696 /* Clearing the memory here */
701 merror("%s: Invalid element '%s' for "
704 elements[j]->element,
712 } /* while(elements[j]) */
714 OS_ClearNode(elements);
717 /* Prematch must be set */
718 if(!prematch && !pi->parent && !p_name)
720 merror(DECODE_NOPRE, ARGV0, pi->name);
721 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
725 /* If pi->regex is not set, fts must not be set too */
726 if((!regex && (pi->fts || pi->order)) || (regex && !pi->order))
728 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
733 /* For the offsets */
734 if(pi->regex_offset & AFTER_PARENT && !pi->parent)
736 merror(INV_OFFSET, ARGV0, "after_parent");
737 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
741 if(pi->regex_offset & AFTER_PREMATCH)
743 /* If after_prematch is set, but rule have
744 * no parent, set AFTER_PARENT and unset
749 pi->regex_offset = 0;
750 pi->regex_offset|= AFTER_PARENT;
754 merror(INV_OFFSET, ARGV0, "after_prematch");
755 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
760 /* For the after_regex offset */
761 if(pi->regex_offset & AFTER_PREVREGEX)
763 if(!pi->parent || !regex)
765 merror(INV_OFFSET, ARGV0, "after_regex");
766 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
772 /* Checking the prematch offset */
773 if(pi->prematch_offset)
775 /* Only the after parent is allowed */
776 if(pi->prematch_offset & AFTER_PARENT)
780 merror(INV_OFFSET, ARGV0, "after_parent");
781 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
787 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
793 /* Compiling the regex/prematch */
796 os_calloc(1, sizeof(OSRegex), pi->prematch);
797 if(!OSRegex_Compile(prematch, pi->prematch, 0))
799 merror(REGEX_COMPILE, ARGV0, prematch, pi->prematch->error);
806 /* Compiling the p_name */
809 os_calloc(1, sizeof(OSMatch), pi->program_name);
810 if(!OSMatch_Compile(p_name, pi->program_name, 0))
812 merror(REGEX_COMPILE, ARGV0, p_name, pi->program_name->error);
819 /* We may not have the pi->regex */
822 os_calloc(1, sizeof(OSRegex), pi->regex);
823 if(!OSRegex_Compile(regex, pi->regex, OS_RETURN_SUBSTRING))
825 merror(REGEX_COMPILE, ARGV0, regex, pi->regex->error);
829 /* We must have the sub_strings to retrieve the nodes */
830 if(!pi->regex->sub_strings)
832 merror(REGEX_SUBS, ARGV0, regex);
840 /* Validating arguments */
841 if(pi->plugindecoder && (pi->regex || pi->order))
843 merror(DECODE_ADD, ARGV0, pi->name);
847 /* Adding osdecoder to the list */
848 if(!OS_AddOSDecoder(pi))
850 merror(DECODER_ERROR, ARGV0);
855 } /* while (node[i]) */
858 /* Cleaning node and XML structures */
873 /* Adding rootcheck decoder to list */
874 addDecoder2list(ROOTCHECK_MOD);
875 addDecoder2list(SYSCHECK_MOD);
876 addDecoder2list(SYSCHECK_MOD2);
877 addDecoder2list(SYSCHECK_MOD3);
878 addDecoder2list(SYSCHECK_NEW);
879 addDecoder2list(SYSCHECK_DEL);
880 addDecoder2list(HOSTINFO_NEW);
881 addDecoder2list(HOSTINFO_MOD);
884 /* Setting ids - for our two lists */
885 if(!os_setdecoderids(NULL))
887 merror(DECODER_ERROR, ARGV0);
890 if(!os_setdecoderids(ARGV0))
892 merror(DECODER_ERROR, ARGV0);
903 * Allocate memory at "*at" and copy *str to it.
904 * If *at already exist, realloc the memory and cat str
906 * It will return the new string
908 char *_loadmemory(char *at, char *str)
913 if((strsize = strlen(str)) < OS_SIZE_1024)
915 at = calloc(strsize+1,sizeof(char));
918 merror(MEM_ERROR,ARGV0);
921 strncpy(at,str,strsize);
926 merror(SIZE_ERROR,ARGV0,str);
930 /* At is not null. Need to reallocat its memory and copy str to it */
933 int strsize = strlen(str);
934 int atsize = strlen(at);
935 int finalsize = atsize+strsize+1;
936 if(finalsize > OS_SIZE_1024)
938 merror(SIZE_ERROR,ARGV0,str);
941 at = realloc(at, (finalsize +1)*sizeof(char));
944 merror(MEM_ERROR,ARGV0);
947 strncat(at,str,strsize);
948 at[finalsize - 1] = '\0';