Imported Upstream version 2.7
[ossec-hids.git] / src / config / localfile-config.c
1 /* @(#) $Id: ./src/config/localfile-config.c, 2012/03/28 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All right reserved.
6  *
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
10  * Foundation
11  */
12
13
14
15 #include "shared.h"
16 #include "localfile-config.h"
17
18
19 int Read_Localfile(XML_NODE node, void *d1, void *d2)
20 {
21     int pl = 0;
22     int i = 0;
23
24     int glob_set = 0;
25
26     #ifndef WIN32
27     int glob_offset = 0;
28     #endif
29
30
31     /* XML Definitions */
32     char *xml_localfile_location = "location";
33     char *xml_localfile_command = "command";
34     char *xml_localfile_logformat = "log_format";
35     char *xml_localfile_frequency = "frequency";
36     char *xml_localfile_alias = "alias";
37
38     logreader *logf;
39     logreader_config *log_config;
40
41     log_config = (logreader_config *)d1;
42
43
44     /* If config is not set, we need to create it */
45     if(!log_config->config)
46     {
47         os_calloc(2, sizeof(logreader), log_config->config);
48         logf = log_config->config;
49         logf[0].file = NULL;
50         logf[0].command = NULL;
51         logf[0].alias = NULL;
52         logf[0].logformat = NULL;
53         logf[1].file = NULL;
54         logf[1].command = NULL;
55         logf[1].alias = NULL;
56         logf[1].logformat = NULL;
57     }
58     else
59     {
60         logf = log_config->config;
61         while(logf[pl].file != NULL)
62         {
63             pl++;
64         }
65
66         /* Allocating more memory */
67         os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
68         logf = log_config->config;
69         logf[pl +1].file = NULL;
70         logf[pl +1].command = NULL;
71         logf[pl +1].alias = NULL;
72         logf[pl +1].logformat = NULL;
73     }
74
75     logf[pl].file = NULL;
76     logf[pl].command = NULL;
77     logf[pl].alias = NULL;
78     logf[pl].logformat = NULL;
79     logf[pl].fp = NULL;
80     logf[pl].ffile = NULL;
81     logf[pl].djb_program_name = NULL;
82     logf[pl].ign = 360;
83
84
85     /* Searching for entries related to files */
86     i = 0;
87     while(node[i])
88     {
89         if(!node[i]->element)
90         {
91             merror(XML_ELEMNULL, ARGV0);
92             return(OS_INVALID);
93         }
94         else if(!node[i]->content)
95         {
96             merror(XML_VALUENULL, ARGV0, node[i]->element);
97             return(OS_INVALID);
98         }
99         else if(strcmp(node[i]->element,xml_localfile_command) == 0)
100         {
101             /* We don't accept remote commands from the manager - just in case. */
102             if(log_config->agent_cfg == 1 && log_config->accept_remote == 0)
103             {
104                 merror("%s: Remote commands are not accepted from the manager. "
105                        "Ignoring it on the agent.conf", ARGV0);
106
107                 logf[pl].file = NULL;
108                 logf[pl].ffile = NULL;
109                 logf[pl].command = NULL;
110                 logf[pl].alias = NULL;
111                 logf[pl].logformat = NULL;
112                 logf[pl].fp = NULL;
113                 return(OS_INVALID);
114             }
115
116             os_strdup(node[i]->content, logf[pl].file);
117             logf[pl].command = logf[pl].file;
118         }
119         else if(strcmp(node[i]->element,xml_localfile_frequency) == 0)
120         {
121             if(!OS_StrIsNum(node[i]->content))
122             {
123                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
124                 return(OS_INVALID);
125             }
126
127             logf[pl].ign = atoi(node[i]->content);
128         }
129         else if(strcmp(node[i]->element,xml_localfile_location) == 0)
130         {
131             #ifdef WIN32
132             /* Expand variables on Windows. */
133             if(strchr(node[i]->content, '%'))
134             {
135                 int expandreturn = 0;
136                 char newfile[OS_MAXSTR +1];
137
138                 newfile[OS_MAXSTR] = '\0';
139                 expandreturn = ExpandEnvironmentStrings(node[i]->content,
140                                                         newfile, OS_MAXSTR);
141
142                 if((expandreturn > 0) && (expandreturn < OS_MAXSTR))
143                 {
144                     free(node[i]->content);
145
146                     os_strdup(newfile, node[i]->content);
147                 }
148             }
149             #endif
150
151
152             /* This is a glob*.
153              * We will call this file multiple times until
154              * there is no one else available.
155              */
156             #ifndef WIN32 /* No windows support for glob */
157             if(strchr(node[i]->content, '*') ||
158                strchr(node[i]->content, '?') ||
159                strchr(node[i]->content, '['))
160             {
161                 glob_t g;
162
163                 /* Setting ot the first entry of the glob */
164                 if(glob_set == 0)
165                     glob_set = pl +1;
166
167                 if(glob(node[i]->content, 0, NULL, &g) != 0)
168                 {
169                     merror(GLOB_ERROR, ARGV0, node[i]->content);
170                     os_strdup(node[i]->content, logf[pl].file);
171                     i++;
172                     continue;
173                 }
174
175                 /* Checking for the last entry */
176                 if((g.gl_pathv[glob_offset]) == NULL)
177                 {
178                     /* Checking when nothing is found. */
179                     if(glob_offset == 0)
180                     {
181                         merror(GLOB_NFOUND, ARGV0, node[i]->content);
182                         return(OS_INVALID);
183                     }
184                     i++;
185                     continue;
186                 }
187
188
189                 /* Checking for strftime on globs too. */
190                 if(strchr(g.gl_pathv[glob_offset], '%'))
191                 {
192                     struct tm *p;
193                     time_t l_time = time(0);
194                     char lfile[OS_FLSIZE + 1];
195                     size_t ret;
196
197                     p = localtime(&l_time);
198
199                     lfile[OS_FLSIZE] = '\0';
200                     ret = strftime(lfile, OS_FLSIZE, g.gl_pathv[glob_offset], p);
201                     if(ret == 0)
202                     {
203                         merror(PARSE_ERROR, ARGV0, g.gl_pathv[glob_offset]);
204                         return(OS_INVALID);
205                     }
206
207                     os_strdup(g.gl_pathv[glob_offset], logf[pl].ffile);
208                     os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
209                 }
210                 else
211                 {
212                     os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
213                 }
214
215
216                 glob_offset++;
217                 globfree(&g);
218
219                 /* Now we need to create another file entry */
220                 pl++;
221                 os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
222                 logf = log_config->config;
223
224                 logf[pl].file = NULL;
225                 logf[pl].alias = NULL;
226                 logf[pl].logformat = NULL;
227                 logf[pl].fp = NULL;
228                 logf[pl].ffile = NULL;
229
230                 logf[pl +1].file = NULL;
231                 logf[pl +1].alias = NULL;
232                 logf[pl +1].logformat = NULL;
233
234                 /* We can not increment the file count in here */
235                 continue;
236             }
237             else if(strchr(node[i]->content, '%'))
238             #else
239             if(strchr(node[i]->content, '%'))
240             #endif /* WIN32 */
241
242             /* We need the format file (based on date) */
243             {
244                 struct tm *p;
245                 time_t l_time = time(0);
246                 char lfile[OS_FLSIZE + 1];
247                 size_t ret;
248
249                 p = localtime(&l_time);
250
251                 lfile[OS_FLSIZE] = '\0';
252                 ret = strftime(lfile, OS_FLSIZE, node[i]->content, p);
253                 if(ret == 0)
254                 {
255                     merror(PARSE_ERROR, ARGV0, node[i]->content);
256                     return(OS_INVALID);
257                 }
258
259                 os_strdup(node[i]->content, logf[pl].ffile);
260                 os_strdup(node[i]->content, logf[pl].file);
261             }
262
263
264             /* Normal file */
265             else
266             {
267                 os_strdup(node[i]->content, logf[pl].file);
268             }
269         }
270
271         /* Getting log format */
272         else if(strcasecmp(node[i]->element,xml_localfile_logformat) == 0)
273         {
274             os_strdup(node[i]->content, logf[pl].logformat);
275
276             if(strcmp(logf[pl].logformat, "syslog") == 0)
277             {
278             }
279             else if(strcmp(logf[pl].logformat, "generic") == 0)
280             {
281             }
282             else if(strcmp(logf[pl].logformat, "snort-full") == 0)
283             {
284             }
285             else if(strcmp(logf[pl].logformat, "snort-fast") == 0)
286             {
287             }
288             else if(strcmp(logf[pl].logformat, "apache") == 0)
289             {
290             }
291             else if(strcmp(logf[pl].logformat, "iis") == 0)
292             {
293             }
294             else if(strcmp(logf[pl].logformat, "squid") == 0)
295             {
296             }
297             else if(strcmp(logf[pl].logformat, "nmapg") == 0)
298             {
299             }
300             else if(strcmp(logf[pl].logformat, "mysql_log") == 0)
301             {
302             }
303             else if(strcmp(logf[pl].logformat, "ossecalert") == 0)
304             {
305             }
306             else if(strcmp(logf[pl].logformat, "mssql_log") == 0)
307             {
308             }
309             else if(strcmp(logf[pl].logformat, "postgresql_log") == 0)
310             {
311             }
312             else if(strcmp(logf[pl].logformat, "djb-multilog") == 0)
313             {
314             }
315             else if(strcmp(logf[pl].logformat, "syslog-pipe") == 0)
316             {
317             }
318             else if(strcmp(logf[pl].logformat, "command") == 0)
319             {
320             }
321             else if(strcmp(logf[pl].logformat, "full_command") == 0)
322             {
323             }
324             else if(strncmp(logf[pl].logformat, "multi-line", 10) == 0)
325             {
326                 int x = 0;
327                 logf[pl].logformat+=10;
328
329                 while(logf[pl].logformat[0] == ' ')
330                     logf[pl].logformat++;
331
332                 if(logf[pl].logformat[0] != ':')
333                 {
334                     merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
335                     return(OS_INVALID);
336                 }
337                 logf[pl].logformat++;
338
339                 while(*logf[pl].logformat == ' ')
340                     logf[pl].logformat++;
341
342                 while(logf[pl].logformat[x] >= '0' && logf[pl].logformat[x] <= '9')
343                     x++;
344
345                 while(logf[pl].logformat[x] == ' ')
346                     x++;
347
348                 if(logf[pl].logformat[x] != '\0')
349                 {
350                     merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
351                     return(OS_INVALID);
352                 }
353             }
354             else if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
355             {
356             }
357             else
358             {
359                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
360                 return(OS_INVALID);
361             }
362         }
363         else if(strcasecmp(node[i]->element,xml_localfile_alias) == 0)
364         {
365             os_strdup(node[i]->content, logf[pl].alias);
366         }
367         else
368         {
369             merror(XML_INVELEM, ARGV0, node[i]->element);
370             return(OS_INVALID);
371         }
372
373         i++;
374     }
375
376
377     /* Validating glob entries */
378     if(glob_set)
379     {
380         char *format;
381
382         /* Getting log format */
383         if(logf[pl].logformat)
384         {
385             format = logf[pl].logformat;
386         }
387         else if(logf[glob_set -1].logformat)
388         {
389             format = logf[glob_set -1].logformat;
390         }
391         else
392         {
393             merror(MISS_LOG_FORMAT, ARGV0);
394             return(OS_INVALID);
395         }
396
397         /* The last entry is always null on glob */
398         pl--;
399
400
401         /* Setting format for all entries */
402         for(i = (glob_set -1); i<= pl; i++)
403         {
404             /* Every entry must be valid */
405             if(!logf[i].file)
406             {
407                 merror(MISS_FILE, ARGV0);
408                 return(OS_INVALID);
409             }
410
411             if(logf[i].logformat == NULL)
412             {
413                 logf[i].logformat = format;
414             }
415
416         }
417     }
418
419     /* Missing log format */
420     if(!logf[pl].logformat)
421     {
422         merror(MISS_LOG_FORMAT, ARGV0);
423         return(OS_INVALID);
424     }
425
426     /* Missing file */
427     if(!logf[pl].file)
428     {
429         merror(MISS_FILE, ARGV0);
430         return(OS_INVALID);
431     }
432
433     /* Verifying a valid event log config */
434     if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
435     {
436         if((strcmp(logf[pl].file, "Application") != 0)&&
437            (strcmp(logf[pl].file, "System") != 0)&&
438            (strcmp(logf[pl].file, "Security") != 0))
439          {
440              /* Invalid event log */
441              merror(NSTD_EVTLOG, ARGV0, logf[pl].file);
442              return(0);
443          }
444     }
445
446     if((strcmp(logf[pl].logformat, "command") == 0)||
447        (strcmp(logf[pl].logformat, "full_command") == 0))
448     {
449         if(!logf[pl].command)
450         {
451             merror("%s: ERROR: Missing 'command' argument. "
452                    "This option will be ignored.", ARGV0);
453         }
454     }
455
456     return(0);
457 }
458
459 /* EOF */