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