1 /* @(#) $Id: ./src/analysisd/decoders/decode-xml.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
12 * License details at the LICENSE file included with OSSEC or
13 * online at: http://www.ossec.net/en/licensing.html
18 #include "os_regex/os_regex.h"
19 #include "os_xml/os_xml.h"
22 #include "analysisd.h"
23 #include "eventinfo.h"
25 #include "plugin_decoders.h"
30 #define XML_LDECODER "etc/local_decoder.xml"
34 /* Internal functions */
35 char *_loadmemory(char *at, char *str);
36 OSStore *os_decoder_store = NULL;
40 int getDecoderfromlist(char *name)
44 return(OSStore_GetPosition(os_decoder_store, name));
52 int addDecoder2list(char *name)
54 if(os_decoder_store == NULL)
56 os_decoder_store = OSStore_Create();
57 if(os_decoder_store == NULL)
59 merror(LIST_ERROR, ARGV0);
65 if(!OSStore_Put(os_decoder_store, name, NULL))
67 merror(LIST_ADD_ERROR, ARGV0);
76 int os_setdecoderids(char *p_name)
79 OSDecoderNode *child_node;
83 node = OS_GetFirstOSDecoder(p_name);
86 /* Return if no node...
87 * This shouldn't happen here anyways.
97 nnode = node->osdecoder;
98 nnode->id = getDecoderfromlist(nnode->name);
100 /* Id can noit be 0 */
106 child_node = node->child;
114 /* Setting parent id */
116 p_name = nnode->name;
119 /* Also setting on the child nodes */
122 nnode = child_node->osdecoder;
124 if(nnode->use_own_name)
126 nnode->id = getDecoderfromlist(nnode->name);
132 /* Setting parent name */
133 nnode->name = p_name;
137 /* Id can noit be 0 */
142 child_node = child_node->next;
144 }while((node=node->next) != NULL);
150 /* Read attributes */
151 int ReadDecodeAttrs(char **names, char **values)
153 if(!names || !values)
156 if(!names[0] || !values[0])
161 if(strcmp(names[0], "offset") == 0)
165 /* Offsets can be: after_parent, after_prematch
168 if(strcmp(values[0],"after_parent") == 0)
170 offset |= AFTER_PARENT;
172 else if(strcmp(values[0],"after_prematch") == 0)
174 offset |= AFTER_PREMATCH;
176 else if(strcmp(values[0],"after_regex") == 0)
178 offset |= AFTER_PREVREGEX;
182 merror(INV_OFFSET, ARGV0, values[0]);
183 offset |= AFTER_ERROR;
189 /* Invalid attribute */
190 merror(INV_ATTR, ARGV0, names[0]);
196 int ReadDecodeXML(char *file)
199 XML_NODE node = NULL;
202 /* These are the available options for the rule configuration */
204 char *xml_plugindecoder = "plugin_decoder";
205 char *xml_decoder = "decoder";
206 char *xml_decoder_name = "name";
207 char *xml_decoder_status = "status";
208 char *xml_usename = "use_own_name";
209 char *xml_parent = "parent";
210 char *xml_program_name = "program_name";
211 char *xml_prematch = "prematch";
212 char *xml_regex = "regex";
213 char *xml_order = "order";
214 char *xml_type = "type";
215 char *xml_fts = "fts";
216 char *xml_ftscomment = "ftscomment";
219 OSDecoderInfo *NULL_Decoder_tmp = NULL;
222 /* Reading the XML */
223 if((i = OS_ReadXML(file,&xml)) < 0)
225 if((i == -2) && (strcmp(file, XML_LDECODER) == 0))
230 merror(XML_ERROR, ARGV0, file, xml.err, xml.err_line);
235 /* Applying any variable found */
236 if(OS_ApplyVariables(&xml) != 0)
238 merror(XML_ERROR_VAR, ARGV0, file, xml.err);
243 /* Getting the root elements */
244 node = OS_GetElementsbyNode(&xml, NULL);
247 if(strcmp(file, XML_LDECODER) != 0)
249 merror(XML_ELEMNULL, ARGV0);
257 /* Zeroing NULL_decoder */
258 os_calloc(1, sizeof(OSDecoderInfo), NULL_Decoder_tmp);
259 NULL_Decoder_tmp->id = 0;
260 NULL_Decoder_tmp->type = SYSLOG;
261 NULL_Decoder_tmp->name = NULL;
262 NULL_Decoder_tmp->fts = 0;
263 NULL_Decoder = (void *)NULL_Decoder_tmp;
270 XML_NODE elements = NULL;
279 if(!node[i]->element ||
280 strcasecmp(node[i]->element, xml_decoder) != 0)
282 merror(XML_INVELEM, ARGV0, node[i]->element);
288 if((!node[i]->attributes) || (!node[i]->values)||
289 (!node[i]->values[0]) || (!node[i]->attributes[0])||
290 (strcasecmp(node[i]->attributes[0],xml_decoder_name)!= 0))
292 merror(XML_INVELEM, ARGV0, node[i]->element);
297 /* Checking for additional entries */
298 if(node[i]->attributes[1] && node[i]->values[1])
300 if(strcasecmp(node[i]->attributes[0],xml_decoder_status)!= 0)
302 merror(XML_INVELEM, ARGV0, node[i]->element);
306 if(node[i]->attributes[2])
308 merror(XML_INVELEM, ARGV0, node[i]->element);
314 /* Getting decoder options */
315 elements = OS_GetElementsbyNode(&xml,node[i]);
318 merror(XML_ELEMNULL, ARGV0);
322 /* Creating the OSDecoderInfo */
323 pi = (OSDecoderInfo *)calloc(1,sizeof(OSDecoderInfo));
326 merror(MEM_ERROR,ARGV0);
331 /* Default values to the list */
334 pi->name = strdup(node[i]->values[0]);
336 pi->plugindecoder = NULL;
340 pi->program_name = NULL;
342 pi->use_own_name = 0;
344 pi->regex_offset = 0;
345 pi->prematch_offset = 0;
352 /* Checking if strdup worked */
355 merror(MEM_ERROR, ARGV0);
360 if(!addDecoder2list(pi->name))
362 merror(MEM_ERROR, ARGV0);
366 /* Looping on all the elements */
369 if(!elements[j]->element)
371 merror(XML_ELEMNULL, ARGV0);
374 else if(!elements[j]->content)
376 merror(XML_VALUENULL, ARGV0, elements[j]->element);
380 /* Checking if it is a child of a rule */
381 else if(strcasecmp(elements[j]->element, xml_parent) == 0)
383 pi->parent = _loadmemory(pi->parent, elements[j]->content);
386 /* Getting the regex */
387 else if(strcasecmp(elements[j]->element,xml_regex) == 0)
390 r_offset = ReadDecodeAttrs(elements[j]->attributes,
391 elements[j]->values);
393 if(r_offset & AFTER_ERROR)
395 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
399 /* Only the first regex entry may have an offset */
400 if(regex && r_offset)
402 merror(DUP_REGEX, ARGV0, pi->name);
403 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
410 pi->regex_offset = r_offset;
416 elements[j]->content);
419 /* Getting the pre match */
420 else if(strcasecmp(elements[j]->element,xml_prematch)==0)
424 r_offset = ReadDecodeAttrs(
425 elements[j]->attributes,
426 elements[j]->values);
428 if(r_offset & AFTER_ERROR)
430 ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
434 /* Only the first prematch entry may have an offset */
435 if(prematch && r_offset)
437 merror(DUP_REGEX, ARGV0, pi->name);
438 ErrorExit(DEC_REGEX_ERROR, ARGV0, pi->name);
443 pi->prematch_offset = r_offset;
447 _loadmemory(prematch,
448 elements[j]->content);
451 /* Getting program name */
452 else if(strcasecmp(elements[j]->element,xml_program_name) == 0)
454 p_name = _loadmemory(p_name, elements[j]->content);
457 /* Getting the fts comment */
458 else if(strcasecmp(elements[j]->element,xml_ftscomment)==0)
462 else if(strcasecmp(elements[j]->element,xml_usename)==0)
464 if(strcmp(elements[j]->content,"true") == 0)
465 pi->use_own_name = 1;
468 else if(strcasecmp(elements[j]->element, xml_plugindecoder) == 0)
471 for(ed_c = 0; plugin_decoders[ed_c] != NULL; ed_c++)
473 if(strcmp(plugin_decoders[ed_c],
474 elements[j]->content) == 0)
476 /* Initializing plugin */
477 void (*dec_init)() = plugin_decoders_init[ed_c];
480 pi->plugindecoder = plugin_decoders_exec[ed_c];
485 /* Decoder not found */
486 if(pi->plugindecoder == NULL)
488 merror(INV_DECOPTION, ARGV0, elements[j]->element,
489 elements[j]->content);
495 /* Getting the type */
496 else if(strcmp(elements[j]->element, xml_type) == 0)
498 if(strcmp(elements[j]->content, "firewall") == 0)
500 else if(strcmp(elements[j]->content, "ids") == 0)
502 else if(strcmp(elements[j]->content, "web-log") == 0)
504 else if(strcmp(elements[j]->content, "syslog") == 0)
506 else if(strcmp(elements[j]->content, "squid") == 0)
508 else if(strcmp(elements[j]->content, "windows") == 0)
510 else if(strcmp(elements[j]->content, "host-information") == 0)
511 pi->type = HOST_INFO;
512 else if(strcmp(elements[j]->content, "ossec") == 0)
516 merror("%s: Invalid decoder type '%s'.",
517 ARGV0, elements[j]->content);
522 /* Getting the order */
523 else if(strcasecmp(elements[j]->element,xml_order)==0)
525 char **norder, **s_norder;
528 /* Maximum number is 8 for the order */
529 norder = OS_StrBreak(',',elements[j]->content, 8);
531 os_calloc(8, sizeof(void *), pi->order);
534 /* Initializing the function pointers */
537 pi->order[order_int] = NULL;
543 /* Checking the values from the order */
546 if(strstr(*norder, "dstuser") != NULL)
548 pi->order[order_int] = (void *)DstUser_FP;
550 else if(strstr(*norder, "srcuser") != NULL)
552 pi->order[order_int] = (void *)SrcUser_FP;
554 /* User is an alias to dstuser */
555 else if(strstr(*norder, "user") != NULL)
557 pi->order[order_int] = (void *)DstUser_FP;
559 else if(strstr(*norder, "srcip") != NULL)
561 pi->order[order_int] = (void *)SrcIP_FP;
563 else if(strstr(*norder, "dstip") != NULL)
565 pi->order[order_int] = (void *)DstIP_FP;
567 else if(strstr(*norder, "srcport") != NULL)
569 pi->order[order_int] = (void *)SrcPort_FP;
571 else if(strstr(*norder, "dstport") != NULL)
573 pi->order[order_int] = (void *)DstPort_FP;
575 else if(strstr(*norder, "protocol") != NULL)
577 pi->order[order_int] = (void *)Protocol_FP;
579 else if(strstr(*norder, "action") != NULL)
581 pi->order[order_int] = (void *)Action_FP;
583 else if(strstr(*norder, "id") != NULL)
585 pi->order[order_int] = (void *)ID_FP;
587 else if(strstr(*norder, "url") != NULL)
589 pi->order[order_int] = (void *)Url_FP;
591 else if(strstr(*norder, "data") != NULL)
593 pi->order[order_int] = (void *)Data_FP;
595 else if(strstr(*norder, "extra_data") != NULL)
597 pi->order[order_int] = (void *)Data_FP;
599 else if(strstr(*norder, "status") != NULL)
601 pi->order[order_int] = (void *)Status_FP;
603 else if(strstr(*norder, "system_name") != NULL)
605 pi->order[order_int] = (void *)SystemName_FP;
609 ErrorExit("decode-xml: Wrong field '%s' in the order"
610 " of decoder '%s'",*norder,pi->name);
622 /* Getting the fts order */
623 else if(strcasecmp(elements[j]->element,xml_fts)==0)
628 /* Maximum number is 8 for the fts */
629 norder = OS_StrBreak(',',elements[j]->content, 8);
631 ErrorExit(MEM_ERROR,ARGV0);
634 /* Saving the initial point to free later */
638 /* Checking the values from the fts */
641 if(strstr(*norder, "dstuser") != NULL)
643 pi->fts|=FTS_DSTUSER;
645 if(strstr(*norder, "user") != NULL)
647 pi->fts|=FTS_DSTUSER;
649 else if(strstr(*norder, "srcuser") != NULL)
651 pi->fts|=FTS_SRCUSER;
653 else if(strstr(*norder, "srcip") != NULL)
657 else if(strstr(*norder, "dstip") != NULL)
661 else if(strstr(*norder, "id") != NULL)
665 else if(strstr(*norder, "location") != NULL)
667 pi->fts|=FTS_LOCATION;
669 else if(strstr(*norder, "data") != NULL)
673 else if(strstr(*norder, "extra_data") != NULL)
677 else if(strstr(*norder, "system_name") != NULL)
679 pi->fts|=FTS_SYSTEMNAME;
681 else if(strstr(*norder, "name") != NULL)
687 ErrorExit("decode-xml: Wrong field '%s' in the fts"
688 " decoder '%s'",*norder, pi->name);
695 /* Clearing the memory here */
700 merror("%s: Invalid element '%s' for "
703 elements[j]->element,
711 } /* while(elements[j]) */
713 OS_ClearNode(elements);
716 /* Prematch must be set */
717 if(!prematch && !pi->parent && !p_name)
719 merror(DECODE_NOPRE, ARGV0, pi->name);
720 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
724 /* If pi->regex is not set, fts must not be set too */
725 if((!regex && (pi->fts || pi->order)) || (regex && !pi->order))
727 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
732 /* For the offsets */
733 if(pi->regex_offset & AFTER_PARENT && !pi->parent)
735 merror(INV_OFFSET, ARGV0, "after_parent");
736 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
740 if(pi->regex_offset & AFTER_PREMATCH)
742 /* If after_prematch is set, but rule have
743 * no parent, set AFTER_PARENT and unset
748 pi->regex_offset = 0;
749 pi->regex_offset|= AFTER_PARENT;
753 merror(INV_OFFSET, ARGV0, "after_prematch");
754 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
759 /* For the after_regex offset */
760 if(pi->regex_offset & AFTER_PREVREGEX)
762 if(!pi->parent || !regex)
764 merror(INV_OFFSET, ARGV0, "after_regex");
765 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
771 /* Checking the prematch offset */
772 if(pi->prematch_offset)
774 /* Only the after parent is allowed */
775 if(pi->prematch_offset & AFTER_PARENT)
779 merror(INV_OFFSET, ARGV0, "after_parent");
780 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
786 merror(DEC_REGEX_ERROR, ARGV0, pi->name);
792 /* Compiling the regex/prematch */
795 os_calloc(1, sizeof(OSRegex), pi->prematch);
796 if(!OSRegex_Compile(prematch, pi->prematch, 0))
798 merror(REGEX_COMPILE, ARGV0, prematch, pi->prematch->error);
805 /* Compiling the p_name */
808 os_calloc(1, sizeof(OSMatch), pi->program_name);
809 if(!OSMatch_Compile(p_name, pi->program_name, 0))
811 merror(REGEX_COMPILE, ARGV0, p_name, pi->program_name->error);
818 /* We may not have the pi->regex */
821 os_calloc(1, sizeof(OSRegex), pi->regex);
822 if(!OSRegex_Compile(regex, pi->regex, OS_RETURN_SUBSTRING))
824 merror(REGEX_COMPILE, ARGV0, regex, pi->regex->error);
828 /* We must have the sub_strings to retrieve the nodes */
829 if(!pi->regex->sub_strings)
831 merror(REGEX_SUBS, ARGV0, regex);
839 /* Validating arguments */
840 if(pi->plugindecoder && (pi->regex || pi->order))
842 merror(DECODE_ADD, ARGV0, pi->name);
846 /* Adding osdecoder to the list */
847 if(!OS_AddOSDecoder(pi))
849 merror(DECODER_ERROR, ARGV0);
854 } /* while (node[i]) */
857 /* Cleaning node and XML structures */
872 /* Adding rootcheck decoder to list */
873 addDecoder2list(ROOTCHECK_MOD);
874 addDecoder2list(SYSCHECK_MOD);
875 addDecoder2list(SYSCHECK_MOD2);
876 addDecoder2list(SYSCHECK_MOD3);
877 addDecoder2list(SYSCHECK_NEW);
878 addDecoder2list(SYSCHECK_DEL);
879 addDecoder2list(HOSTINFO_NEW);
880 addDecoder2list(HOSTINFO_MOD);
883 /* Setting ids - for our two lists */
884 if(!os_setdecoderids(NULL))
886 merror(DECODER_ERROR, ARGV0);
889 if(!os_setdecoderids(ARGV0))
891 merror(DECODER_ERROR, ARGV0);
902 * Allocate memory at "*at" and copy *str to it.
903 * If *at already exist, realloc the memory and cat str
905 * It will return the new string
907 char *_loadmemory(char *at, char *str)
912 if((strsize = strlen(str)) < OS_SIZE_1024)
914 at = calloc(strsize+1,sizeof(char));
917 merror(MEM_ERROR,ARGV0);
920 strncpy(at,str,strsize);
925 merror(SIZE_ERROR,ARGV0,str);
929 /* At is not null. Need to reallocat its memory and copy str to it */
932 int strsize = strlen(str);
933 int atsize = strlen(at);
934 int finalsize = atsize+strsize+1;
935 if(finalsize > OS_SIZE_1024)
937 merror(SIZE_ERROR,ARGV0,str);
940 at = realloc(at, (finalsize +1)*sizeof(char));
943 merror(MEM_ERROR,ARGV0);
946 strncat(at,str,strsize);
947 at[finalsize - 1] = '\0';