new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / config / 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 /* Unified function to read the configuration */
11
12 #include <libgen.h>
13 #include "shared.h"
14 #include "os_xml/os_xml.h"
15 #include "config.h"
16
17 /* Prototypes */
18 static int read_main_elements(const OS_XML *xml, int modules,
19                               XML_NODE node,
20                               void *d1,
21                               void *d2);
22
23
24 /* Read the main elements of the configuration */
25 static int read_main_elements(const OS_XML *xml, int modules,
26                               XML_NODE node,
27                               void *d1,
28                               void *d2)
29 {
30     int i = 0;
31     const char *osglobal = "global";                    /* Server Config */
32     const char *osrules = "rules";                      /* Server Config */
33     const char *ossyscheck = "syscheck";                /* Agent Config  */
34     const char *osrootcheck = "rootcheck";              /* Agent Config  */
35     const char *osalerts = "alerts";                    /* Server Config */
36     const char *osemailalerts = "email_alerts";         /* Server Config */
37     const char *osdbd = "database_output";              /* Server Config */
38     const char *oscsyslogd = "syslog_output";           /* Server Config */
39     const char *oscagentless = "agentless";             /* Server Config */
40     const char *oslocalfile = "localfile";              /* Agent Config  */
41     const char *osremote = "remote";                    /* Agent Config  */
42     const char *osclient = "client";                    /* Agent Config  */
43     const char *oscommand = "command";                  /* ? Config      */
44     const char *osreports = "reports";                  /* Server Config */
45     const char *osactive_response = "active-response";  /* Agent Config  */
46
47     while (node[i]) {
48         XML_NODE chld_node = NULL;
49
50         if (!node[i]->element) {
51             merror(XML_ELEMNULL, __local_name);
52             goto fail;
53         } else if (!(chld_node = OS_GetElementsbyNode(xml, node[i]))) {
54             merror(XML_INVELEM, __local_name, node[i]->element);
55             goto fail;
56         } else if (strcmp(node[i]->element, osglobal) == 0) {
57             if (((modules & CGLOBAL) || (modules & CMAIL))
58                     && (Read_Global(chld_node, d1, d2) < 0)) {
59                 goto fail;
60             }
61         } else if (strcmp(node[i]->element, osemailalerts) == 0) {
62             if ((modules & CMAIL) && (Read_EmailAlerts(chld_node, d1, d2) < 0)) {
63                 goto fail;
64             }
65         } else if (strcmp(node[i]->element, osdbd) == 0) {
66             if ((modules & CDBD) && (Read_DB(chld_node, d1, d2) < 0)) {
67                 goto fail;
68             }
69         } else if (strcmp(node[i]->element, oscsyslogd) == 0) {
70             if ((modules & CSYSLOGD) && (Read_CSyslog(chld_node, d1, d2) < 0)) {
71                 goto fail;
72             }
73         } else if (strcmp(node[i]->element, oscagentless) == 0) {
74             if ((modules & CAGENTLESS) && (Read_CAgentless(chld_node, d1, d2) < 0)) {
75                 goto fail;
76             }
77         } else if (strcmp(node[i]->element, osrules) == 0) {
78             if ((modules & CRULES) && (Read_Rules(chld_node, d1, d2) < 0)) {
79                 goto fail;
80             }
81         } else if (strcmp(node[i]->element, ossyscheck) == 0) {
82             if ((modules & CSYSCHECK) && (Read_Syscheck(chld_node, d1, d2) < 0)) {
83                 goto fail;
84             }
85             if ((modules & CGLOBAL) && (Read_GlobalSK(chld_node, d1, d2) < 0)) {
86                 goto fail;
87             }
88         } else if (strcmp(node[i]->element, osrootcheck) == 0) {
89             if ((modules & CROOTCHECK) && (Read_Rootcheck(chld_node, d1, d2) < 0)) {
90                 goto fail;
91             }
92         } else if (strcmp(node[i]->element, osalerts) == 0) {
93             if ((modules & CALERTS) && (Read_Alerts(chld_node, d1, d2) < 0)) {
94                 goto fail;
95             }
96         } else if (strcmp(node[i]->element, oslocalfile) == 0) {
97             if ((modules & CLOCALFILE) && (Read_Localfile(chld_node, d1, d2) < 0)) {
98                 goto fail;
99             }
100         } else if (strcmp(node[i]->element, osremote) == 0) {
101             if ((modules & CREMOTE) && (Read_Remote(chld_node, d1, d2) < 0)) {
102                 goto fail;
103             }
104         } else if (strcmp(node[i]->element, osclient) == 0) {
105             if ((modules & CCLIENT) && (Read_Client(chld_node, d1, d2) < 0)) {
106                 goto fail;
107             }
108         } else if (strcmp(node[i]->element, oscommand) == 0) {
109             if ((modules & CAR) && (ReadActiveCommands(chld_node, d1, d2) < 0)) {
110                 goto fail;
111             }
112         } else if (strcmp(node[i]->element, osactive_response) == 0) {
113             if ((modules & CAR) && (ReadActiveResponses(chld_node, d1, d2) < 0)) {
114                 goto fail;
115             }
116         } else if (strcmp(node[i]->element, osreports) == 0) {
117             if ((modules & CREPORTS) && (Read_CReports(chld_node, d1, d2) < 0)) {
118                 goto fail;
119             }
120         } else {
121             merror(XML_INVELEM, __local_name, node[i]->element);
122             goto fail;
123         }
124
125         OS_ClearNode(chld_node);
126         i++;
127
128         continue;
129
130         fail:
131         OS_ClearNode(chld_node);
132         return (OS_INVALID);
133     }
134
135     return (0);
136 }
137
138 /* Read the config files */
139 int ReadConfig(int modules, const char *cfgfile, void *d1, void *d2)
140 {
141     int i;
142     OS_XML xml;
143     XML_NODE node;
144
145     /** XML definitions **/
146     /* Global */
147     const char *xml_start_ossec = "ossec_config";
148     const char *xml_start_agent = "agent_config";
149
150     /* Attributes of the <agent_config> tag */
151     const char *xml_agent_name = "name";
152     const char *xml_agent_os = "os";
153     const char *xml_agent_overwrite = "overwrite";
154     const char *xml_agent_profile = "profile";
155
156     int xml_ret = OS_ReadXML(cfgfile, &xml);
157     if (xml_ret < 0) {
158         char *tmpcfg;
159         tmpcfg = strdup(cfgfile);
160         const char *cfg_base = basename(tmpcfg);
161             if((strncmp(cfg_base, "agent.conf", 10)) == 0 && xml_ret == -2) {
162                     debug2("WARN: Cannot open %s: %s", cfgfile, xml.err);
163             } else {
164                     merror(XML_ERROR, __local_name, cfgfile, xml.err, xml.err_line);
165             }
166         return (OS_INVALID);
167     }
168
169     node = OS_GetElementsbyNode(&xml, NULL);
170     if (!node) {
171         return (0);
172     }
173
174     /* Read the main configuration */
175     i = 0;
176     while (node[i]) {
177         if (!node[i]->element) {
178             merror(XML_ELEMNULL, __local_name);
179             OS_ClearNode(node);
180             return (OS_INVALID);
181         } else if (!(modules & CAGENT_CONFIG) &&
182                    (strcmp(node[i]->element, xml_start_ossec) == 0)) {
183             XML_NODE chld_node = NULL;
184             chld_node = OS_GetElementsbyNode(&xml, node[i]);
185
186             /* Main element does not need to have any child */
187             if (chld_node) {
188                 if (read_main_elements(&xml, modules, chld_node, d1, d2) < 0) {
189                     merror(CONFIG_ERROR, __local_name, cfgfile);
190                     OS_ClearNode(chld_node);
191                     OS_ClearNode(node);
192                     return (OS_INVALID);
193                 }
194
195                 OS_ClearNode(chld_node);
196             }
197         } else if ((modules & CAGENT_CONFIG) &&
198                    (strcmp(node[i]->element, xml_start_agent) == 0)) {
199             int passed_agent_test = 1;
200             int attrs = 0;
201             XML_NODE chld_node = NULL;
202             chld_node = OS_GetElementsbyNode(&xml, node[i]);
203
204             /* Check if this is specific to any agent */
205             if (node[i]->attributes && node[i]->values) {
206                 while (node[i]->attributes[attrs] && node[i]->values[attrs]) {
207                     /* Check if there is an "name=" attribute */
208                     if (strcmp(xml_agent_name, node[i]->attributes[attrs]) == 0) {
209 #ifdef CLIENT
210                         char *agentname = os_read_agent_name();
211
212                         if (!agentname) {
213                             passed_agent_test = 0;
214                         } else {
215                             if (!OS_Match2(node[i]->values[attrs], agentname)) {
216                                 passed_agent_test = 0;
217                             }
218                             free(agentname);
219                         }
220 #endif
221                     } else if (strcmp(xml_agent_os, node[i]->attributes[attrs]) == 0) {
222 #ifdef CLIENT
223                         char *agentos = getuname();
224
225                         if (agentos) {
226                             if (!OS_Match2(node[i]->values[attrs], agentos)) {
227                                 passed_agent_test = 0;
228                             }
229                             free(agentos);
230                         } else {
231                             passed_agent_test = 0;
232                             merror("%s: ERROR: Unable to retrieve uname.", __local_name);
233                         }
234 #endif
235                     } else if (strcmp(xml_agent_profile, node[i]->attributes[attrs]) == 0) {
236 #ifdef CLIENT
237                         char *agentprofile = os_read_agent_profile();
238                         debug2("Read agent config profile name [%s]", agentprofile);
239
240                         if (!agentprofile) {
241                             passed_agent_test = 0;
242                         } else {
243                             /* match the profile name of this <agent_config> section
244                              * with a comma separated list of values in agent's
245                              * <config-profile> tag.
246                              */
247                             if (!OS_Match2(node[i]->values[attrs], agentprofile)) {
248                                 passed_agent_test = 0;
249                                 debug2("[%s] did not match agent config profile name [%s]",
250                                        node[i]->values[attrs], agentprofile);
251                             } else {
252                                 debug2("Matched agent config profile name [%s]", agentprofile);
253                             }
254                             free(agentprofile);
255                         }
256 #endif
257                     } else if (strcmp(xml_agent_overwrite, node[i]->attributes[attrs]) == 0) {
258                     } else {
259                         merror(XML_INVATTR, __local_name, node[i]->attributes[attrs],
260                                cfgfile);
261                     }
262                     attrs++;
263                 }
264             }
265 #ifdef CLIENT
266             else {
267                 debug2("agent_config element does not have any attributes.");
268
269                 /* if node does not have any attributes, it is a generic config block.
270                  * check if agent has a profile name
271                  * if agent does not have profile name, then only read this generic
272                  * agent_config block
273                  */
274
275                 if (!os_read_agent_profile()) {
276                     debug2("but agent has a profile name.");
277                     passed_agent_test = 0;
278                 }
279             }
280 #endif
281
282             /* Main element does not need to have any child */
283             if (chld_node) {
284                 if (passed_agent_test && read_main_elements(&xml, modules, chld_node, d1, d2) < 0) {
285                     merror(CONFIG_ERROR, __local_name, cfgfile);
286                     OS_ClearNode(chld_node);
287                     OS_ClearNode(node);
288                     return (OS_INVALID);
289                 }
290
291                 OS_ClearNode(chld_node);
292             }
293         } else {
294             merror(XML_INVELEM, __local_name, node[i]->element);
295             OS_ClearNode(node);
296             return (OS_INVALID);
297         }
298         i++;
299     }
300
301     /* Clear node and xml */
302     OS_ClearNode(node);
303     OS_ClearXML(&xml);
304     return (0);
305 }
306