new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / config / csyslogd-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 "csyslogd-config.h"
11 #include "config.h"
12
13
14 int Read_CSyslog(XML_NODE node, void *config, __attribute__((unused)) void *config2)
15 {
16     unsigned int i = 0, s = 0;
17
18     /* XML definitions */
19     const char *xml_syslog_server = "server";
20     const char *xml_syslog_port = "port";
21     const char *xml_syslog_format = "format";
22     const char *xml_syslog_level = "level";
23     const char *xml_syslog_id = "rule_id";
24     const char *xml_syslog_group = "group";
25     const char *xml_syslog_location = "location";
26     const char *xml_syslog_use_fqdn = "use_fqdn";
27
28     struct SyslogConfig_holder *config_holder = (struct SyslogConfig_holder *)config;
29     SyslogConfig **syslog_config = config_holder->data;
30
31     if (syslog_config) {
32         while (syslog_config[s]) {
33             s++;
34         }
35     }
36
37     /* Allocate the memory for the config */
38     os_realloc(syslog_config, (s + 2) * sizeof(SyslogConfig *), syslog_config);
39     os_calloc(1, sizeof(SyslogConfig), syslog_config[s]);
40     syslog_config[s + 1] = NULL;
41
42     /* Zero the elements */
43     syslog_config[s]->server = NULL;
44     syslog_config[s]->rule_id = NULL;
45     syslog_config[s]->group = NULL;
46     syslog_config[s]->location = NULL;
47     syslog_config[s]->level = 0;
48     syslog_config[s]->port = "514";
49     syslog_config[s]->format = DEFAULT_CSYSLOG;
50     syslog_config[s]->use_fqdn = 0;
51     /* local 0 facility (16) + severity 4 - warning. --default */
52     syslog_config[s]->priority = (16 * 8) + 4;
53
54     while (node[i]) {
55         if (!node[i]->element) {
56             merror(XML_ELEMNULL, __local_name);
57             goto fail;
58         } else if (!node[i]->content) {
59             merror(XML_VALUENULL, __local_name, node[i]->element);
60             goto fail;
61         } else if (strcmp(node[i]->element, xml_syslog_level) == 0) {
62             if (!OS_StrIsNum(node[i]->content)) {
63                 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
64                 goto fail;
65             }
66
67             syslog_config[s]->level = (unsigned int) atoi(node[i]->content);
68         } else if (strcmp(node[i]->element, xml_syslog_port) == 0) {
69             if (!OS_StrIsNum(node[i]->content)) {
70                 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
71                 goto fail;
72             }
73
74             os_strdup(node[i]->content, syslog_config[s]->port);
75         } else if (strcmp(node[i]->element, xml_syslog_server) == 0) {
76             os_strdup(node[i]->content, syslog_config[s]->server);
77         } else if (strcmp(node[i]->element, xml_syslog_id) == 0) {
78             unsigned int r_id = 0;
79             char *str_pt = node[i]->content;
80
81             while (*str_pt != '\0') {
82                 /* We allow spaces in between */
83                 if (*str_pt == ' ') {
84                     str_pt++;
85                     continue;
86                 }
87
88                 /* If is digit, we get the value
89                  * and search for the next digit
90                  * available
91                  */
92                 else if (isdigit((int)*str_pt)) {
93                     unsigned int id_i = 0;
94
95                     r_id = (unsigned int) atoi(str_pt);
96                     debug1("%s: DEBUG: Adding '%d' to syslog alerting",
97                            __local_name, r_id);
98
99                     if (syslog_config[s]->rule_id) {
100                         while (syslog_config[s]->rule_id[id_i]) {
101                             id_i++;
102                         }
103                     }
104
105                     os_realloc(syslog_config[s]->rule_id,
106                                (id_i + 2) * sizeof(unsigned int),
107                                syslog_config[s]->rule_id);
108
109                     syslog_config[s]->rule_id[id_i + 1] = 0;
110                     syslog_config[s]->rule_id[id_i] = r_id;
111
112                     str_pt = strchr(str_pt, ',');
113                     if (str_pt) {
114                         str_pt++;
115                     } else {
116                         break;
117                     }
118                 }
119
120                 /* Check for duplicate commas */
121                 else if (*str_pt == ',') {
122                     str_pt++;
123                     continue;
124                 }
125
126                 else {
127                     break;
128                 }
129             }
130
131         } else if (strcmp(node[i]->element, xml_syslog_format) == 0) {
132             if (strcmp(node[i]->content, "default") == 0) {
133                 /* Default is full format */
134             } else if (strcmp(node[i]->content, "cef") == 0) {
135                 /* Enable the CEF format */
136                 syslog_config[s]->format = CEF_CSYSLOG;
137             } else if (strcmp(node[i]->content, "json") == 0) {
138                 /* Enable the JSON format */
139                 syslog_config[s]->format = JSON_CSYSLOG;
140             } else if (strcmp(node[i]->content, "splunk") == 0) {
141                 /* Enable the Splunk Key/Value format */
142                 syslog_config[s]->format = SPLUNK_CSYSLOG;
143             } else {
144                 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
145                 goto fail;
146             }
147         } else if (strcmp(node[i]->element, xml_syslog_location) == 0) {
148             os_calloc(1, sizeof(OSMatch), syslog_config[s]->location);
149             if (!OSMatch_Compile(node[i]->content,
150                                  syslog_config[s]->location, 0)) {
151                 merror(REGEX_COMPILE, __local_name, node[i]->content,
152                        syslog_config[s]->location->error);
153                 goto fail;
154             }
155         } else if (strcmp(node[i]->element, xml_syslog_use_fqdn) == 0) {
156             if (strcmp(node[i]->content, "yes") == 0) {
157                 syslog_config[s]->use_fqdn = 1;
158             } else if (strcmp(node[i]->content, "no") == 0) {
159                 syslog_config[s]->use_fqdn = 0;
160             } else {
161                 merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
162                 goto fail;
163             }
164         } else if (strcmp(node[i]->element, xml_syslog_group) == 0) {
165             os_calloc(1, sizeof(OSMatch), syslog_config[s]->group);
166             if (!OSMatch_Compile(node[i]->content,
167                                  syslog_config[s]->group, 0)) {
168                 merror(REGEX_COMPILE, __local_name, node[i]->content,
169                        syslog_config[s]->group->error);
170                 goto fail;
171             }
172         } else {
173             merror(XML_INVELEM, __local_name, node[i]->element);
174             goto fail;
175         }
176         i++;
177     }
178
179     /* We must have at least one entry set */
180     if (!syslog_config[s]->server) {
181         merror(XML_INV_CSYSLOG, __local_name);
182         goto fail;
183     }
184
185     config_holder->data = syslog_config;
186     return (0);
187
188 fail:
189     i = 0;
190     while (syslog_config[i]) {
191         free(syslog_config[i]->server);
192
193         if (syslog_config[i]->group) {
194             OSMatch_FreePattern(syslog_config[i]->group);
195         }
196
197         if (syslog_config[i]->location) {
198             OSMatch_FreePattern(syslog_config[i]->location);
199         }
200
201         free(syslog_config[i]->rule_id);
202
203         ++i;
204     }
205     free(syslog_config);
206     return (OS_INVALID);
207 }
208