new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / config / reports-config.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All right reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 #include "shared.h"
11 #include "reports-config.h"
12 #include "config.h"
13
14
15 /* Filter argument */
16 static int _filter_arg(char *mystr)
17 {
18     if (!mystr) {
19         return (0);
20     }
21
22     while (*mystr) {
23         if ((*mystr >= 'a' && *mystr <= 'z') ||
24                 (*mystr >= 'A' && *mystr <= 'Z') ||
25                 (*mystr >= '0' && *mystr <= '9') ||
26                 *mystr == '-' || *mystr == '_' || *mystr == '.') {
27             mystr++;
28         } else {
29             *mystr = '-';
30             mystr++;
31         }
32     }
33
34     return (1);
35 }
36
37 int Read_CReports(XML_NODE node, void *config, __attribute__((unused)) void *config2)
38 {
39     unsigned int i = 0, s = 0;
40
41     /* XML definitions */
42     const char *xml_title = "title";
43     const char *xml_type = "type";
44     const char *xml_categories = "category";
45     const char *xml_group = "group";
46     const char *xml_rule = "rule";
47     const char *xml_level = "level";
48     const char *xml_location = "location";
49     const char *xml_showlogs = "showlogs";
50     const char *xml_srcip = "srcip";
51     const char *xml_user = "user";
52     const char *xml_frequency = "frequency";
53     const char *xml_email = "email_to";
54
55     monitor_config *mon_config = (monitor_config *)config;
56
57     /* Get any configured entry */
58     if (mon_config->reports) {
59         while (mon_config->reports[s]) {
60             s++;
61         }
62     }
63
64     /* Allocate the memory for the config */
65     os_realloc(mon_config->reports, (s + 2) * sizeof(report_config *),
66                mon_config->reports);
67     os_calloc(1, sizeof(report_config), mon_config->reports[s]);
68     mon_config->reports[s + 1] = NULL;
69
70     /* Zero the elements */
71     mon_config->reports[s]->title = NULL;
72     mon_config->reports[s]->args = NULL;
73     mon_config->reports[s]->relations = NULL;
74     mon_config->reports[s]->type = NULL;
75     mon_config->reports[s]->emailto = NULL;
76
77     mon_config->reports[s]->r_filter.group = NULL;
78     mon_config->reports[s]->r_filter.rule = NULL;
79     mon_config->reports[s]->r_filter.level = NULL;
80     mon_config->reports[s]->r_filter.location = NULL;
81     mon_config->reports[s]->r_filter.srcip = NULL;
82     mon_config->reports[s]->r_filter.user = NULL;
83     mon_config->reports[s]->r_filter.related_group = 0;
84     mon_config->reports[s]->r_filter.related_rule = 0;
85     mon_config->reports[s]->r_filter.related_level = 0;
86     mon_config->reports[s]->r_filter.related_location = 0;
87     mon_config->reports[s]->r_filter.related_srcip = 0;
88     mon_config->reports[s]->r_filter.related_user = 0;
89     mon_config->reports[s]->r_filter.report_name = NULL;
90     mon_config->reports[s]->r_filter.show_alerts = 0;
91
92     /* Reading the XML */
93     while (node[i]) {
94         if (!node[i]->element) {
95             merror(XML_ELEMNULL, __local_name);
96             return (OS_INVALID);
97         } else if (!node[i]->content) {
98             merror(XML_VALUENULL, __local_name, node[i]->element);
99             return (OS_INVALID);
100         } else if (strcmp(node[i]->element, xml_title) == 0) {
101             if (!mon_config->reports[s]->title) {
102                 os_strdup(node[i]->content, mon_config->reports[s]->title);
103             }
104         } else if (strcmp(node[i]->element, xml_type) == 0) {
105             if (strcmp(node[i]->content, "email") == 0) {
106                 if (!mon_config->reports[s]->type) {
107                     os_strdup(node[i]->content, mon_config->reports[s]->type);
108                 }
109             } else {
110                 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
111             }
112         } else if (strcmp(node[i]->element, xml_frequency) == 0) {
113         } else if (strcmp(node[i]->element, xml_showlogs) == 0) {
114             if (strcasecmp(node[i]->content, "yes") == 0) {
115                 mon_config->reports[s]->r_filter.show_alerts = 1;
116             }
117         } else if (strcmp(node[i]->element, xml_categories) == 0) {
118             char *ncat = NULL;
119             _filter_arg(node[i]->content);
120
121             os_strdup(node[i]->content, ncat);
122
123             if (os_report_configfilter("group", ncat,
124                                        &mon_config->reports[s]->r_filter, REPORT_FILTER) < 0) {
125                 merror(CONFIG_ERROR, __local_name, "user argument");
126             }
127         } else if ((strcmp(node[i]->element, xml_group) == 0) ||
128                    (strcmp(node[i]->element, xml_rule) == 0) ||
129                    (strcmp(node[i]->element, xml_level) == 0) ||
130                    (strcmp(node[i]->element, xml_location) == 0) ||
131                    (strcmp(node[i]->element, xml_srcip) == 0) ||
132                    (strcmp(node[i]->element, xml_user) == 0)) {
133             int reportf = REPORT_FILTER;
134             char *ncat = NULL;
135             _filter_arg(node[i]->content);
136
137             if (node[i]->attributes && node[i]->values) {
138                 if (node[i]->attributes[0] && node[i]->values[0]) {
139                     if (strcmp(node[i]->attributes[0], "type") == 0) {
140                         if (strcmp(node[i]->values[0], "relation") == 0) {
141                             reportf = REPORT_RELATED;
142                         } else {
143                             merror("%s: WARN: Invalid value for 'relation' attribute: '%s'. (ignored).", __local_name, node[i]->values[0]);
144                             i++;
145                             continue;
146                         }
147                     } else {
148                         merror("%s: WARN: Invalid attribute: %s (ignored). ", __local_name, node[i]->attributes[0]);
149                         i++;
150                         continue;
151                     }
152                 }
153             }
154
155             os_strdup(node[i]->content, ncat);
156
157             if (os_report_configfilter(node[i]->element, ncat,
158                                        &mon_config->reports[s]->r_filter, reportf) < 0) {
159                 merror("%s: Invalid filter: %s:%s (ignored).", __local_name, node[i]->element, node[i]->content);
160             }
161         } else if (strcmp(node[i]->element, xml_email) == 0) {
162             mon_config->reports[s]->emailto = os_AddStrArray(node[i]->content, mon_config->reports[s]->emailto);
163         } else {
164             merror(XML_INVELEM, __local_name, node[i]->element);
165             return (OS_INVALID);
166         }
167         i++;
168     }
169
170     /* Set proper report type */
171     mon_config->reports[s]->r_filter.report_type = REPORT_TYPE_DAILY;
172
173     if (mon_config->reports[s]->emailto == NULL) {
174         if (mon_config->reports[s]->title) {
175             merror("%s: No \"email to\" configured for the report '%s'. Ignoring it.", __local_name, mon_config->reports[s]->title);
176         } else {
177             merror("%s: No \"email to\" and title configured for report. Ignoring it.", __local_name);
178         }
179     }
180
181     if (!mon_config->reports[s]->title) {
182         os_strdup("OSSEC Report (unnamed)", mon_config->reports[s]->title);
183     }
184     mon_config->reports[s]->r_filter.report_name = mon_config->reports[s]->title;
185
186     return (0);
187 }
188